Skip to content

Commit

Permalink
Merge pull request #150 from SainsburyWellcomeCentre/gl-dev
Browse files Browse the repository at this point in the history
Add reusable operators for room light control using presets and configurable light cycle
  • Loading branch information
glopesdev authored Oct 11, 2023
2 parents 50f3df0 + ad0c1cc commit 74d169d
Show file tree
Hide file tree
Showing 16 changed files with 1,103 additions and 44 deletions.
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"bonsai.sgen": {
"version": "0.1.0",
"commands": [
"bonsai.sgen"
]
}
}
}
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

The Project Aeon acquisition repository contains the set of standardized data acquisition systems, protocols, operation instructions and metadata necessary for reproducible task control and acquisition on the foraging arena assay. The scripts contained in this repository should always represent as accurately as possible the automation routines and operational instructions used to log the experimental raw data for Project Aeon. Each acquired dataset should have a reference to the specific hash or release from this repository which was used in the experiment.

## Build Instructions

### Schema classes

1. Install [`bonsai.sgen`](https://www.nuget.org/packages/Bonsai.Sgen) by running the `restore` command:

```
dotnet tool restore
```
2. Run the command to regenerate each schema class, e.g. for `ChannelMap.json`:
```
dotnet bonsai.sgen --namespace Aeon.Environment --schema ChannelMap.json
```
## Deployment Instructions
The Project Aeon acquisition framework runs on the [Bonsai](https://bonsai-rx.org/) visual programming language. This repository includes installation scripts which will automatically download and configure a reproducible, self-contained, Bonsai environment to run all acquisition systems on the foraging arena. It is necessary, however, to install a few system dependencies and device drivers which need to be installed separately, before runnning the environment configuration script.
Expand Down
4 changes: 2 additions & 2 deletions src/Aeon.Acquisition/Aeon.Acquisition.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<PackageTags>Bonsai Rx Project Aeon Acquisition</PackageTags>
<TargetFramework>net472</TargetFramework>
<VersionPrefix>0.5.0</VersionPrefix>
<VersionSuffix>build230924</VersionSuffix>
<VersionSuffix>build231005</VersionSuffix>
</PropertyGroup>

<ItemGroup>
Expand All @@ -30,7 +30,7 @@
<PackageReference Include="Bonsai.ZeroMQ" Version="0.2.0" />
<PackageReference Include="LibGit2Sharp" Version="0.25.4" />
<PackageReference Include="Bonsai.Vision" Version="2.8.0" />
<PackageReference Include="Bonsai.Numerics" Version="0.8.0" />
<PackageReference Include="Bonsai.Numerics" Version="0.9.0" />
</ItemGroup>

</Project>
30 changes: 30 additions & 0 deletions src/Aeon.Acquisition/GetDateTime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using Bonsai;
using Bonsai.Harp;

namespace Aeon.Acquisition
{
[Combinator]
[WorkflowElementCategory(ElementCategory.Transform)]
[Description("Converts a sequence of referenced Harp timestamps into system date-time objects.")]
public class GetDateTime
{
static DateTime FromSeconds(double seconds)
{
return GroupByTime.ReferenceTime.AddSeconds(seconds);
}

public IObservable<DateTime> Process(IObservable<HarpMessage> source)
{
return source.Select(message => FromSeconds(message.GetTimestamp()));
}

public IObservable<DateTime> Process<T>(IObservable<Timestamped<T>> source)
{
return source.Select(_ => FromSeconds(_.Seconds));
}
}
}
2 changes: 1 addition & 1 deletion src/Aeon.Acquisition/GroupByTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public GroupByTime()
}

// The default real-time reference is unix time in total seconds from 1904
static readonly DateTime ReferenceTime = new DateTime(1904, 1, 1);
internal static readonly DateTime ReferenceTime = new(1904, 1, 1);

[Description("The size of each chunk, in whole hours.")]
public int ChunkSize { get; set; }
Expand Down
295 changes: 295 additions & 0 deletions src/Aeon.Environment/Aeon.Environment.Generated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
//----------------------
// <auto-generated>
// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v9.0.0.0) (http://NJsonSchema.org)
// </auto-generated>
//----------------------


namespace Aeon.Environment
{
#pragma warning disable // Disable all warnings

/// <summary>
/// Specifies the channel map for every light fixture in the room.
/// </summary>
[System.ComponentModel.DescriptionAttribute("Specifies the channel map for every light fixture in the room.")]
[Bonsai.CombinatorAttribute()]
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
public partial class RoomFixtures
{

private Fixture _coldWhite;

private Fixture _warmWhite;

private Fixture _red;

[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="coldWhite")]
public Fixture ColdWhite
{
get
{
return _coldWhite;
}
set
{
_coldWhite = value;
}
}

[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="warmWhite")]
public Fixture WarmWhite
{
get
{
return _warmWhite;
}
set
{
_warmWhite = value;
}
}

[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="red")]
public Fixture Red
{
get
{
return _red;
}
set
{
_red = value;
}
}

public System.IObservable<RoomFixtures> Process()
{
return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(
new RoomFixtures
{
ColdWhite = _coldWhite,
WarmWhite = _warmWhite,
Red = _red
}));
}
}


[Bonsai.CombinatorAttribute()]
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
public partial class Fixture
{

private System.Collections.Generic.List<int> _channels = new System.Collections.Generic.List<int>();

private InterpolationMethod _interpolationMethod;

private string _calibrationFile;

/// <summary>
/// Specifies the collection of channels assigned to the fixture.
/// </summary>
[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="channels")]
[System.ComponentModel.DescriptionAttribute("Specifies the collection of channels assigned to the fixture.")]
public System.Collections.Generic.List<int> Channels
{
get
{
return _channels;
}
set
{
_channels = value;
}
}

/// <summary>
/// Specifies the method used to interpolate light values for a fixture.
/// </summary>
[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="interpolationMethod")]
[System.ComponentModel.DescriptionAttribute("Specifies the method used to interpolate light values for a fixture.")]
public InterpolationMethod InterpolationMethod
{
get
{
return _interpolationMethod;
}
set
{
_interpolationMethod = value;
}
}

/// <summary>
/// Specifies the path to the calibration file for this fixture.
/// </summary>
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="calibrationFile")]
[System.ComponentModel.DescriptionAttribute("Specifies the path to the calibration file for this fixture.")]
public string CalibrationFile
{
get
{
return _calibrationFile;
}
set
{
_calibrationFile = value;
}
}

public System.IObservable<Fixture> Process()
{
return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(
new Fixture
{
Channels = _channels,
InterpolationMethod = _interpolationMethod,
CalibrationFile = _calibrationFile
}));
}
}


/// <summary>
/// Specifies the method used to interpolate light values for a fixture.
/// </summary>
public enum InterpolationMethod
{

[YamlDotNet.Serialization.YamlMemberAttribute(Alias="None")]
None = 0,

[YamlDotNet.Serialization.YamlMemberAttribute(Alias="Zero")]
Zero = 1,

[YamlDotNet.Serialization.YamlMemberAttribute(Alias="Linear")]
Linear = 2,
}


/// <summary>
/// Represents channel map configuration used by the light controller.
/// </summary>
[System.ComponentModel.DescriptionAttribute("Represents channel map configuration used by the light controller.")]
[Bonsai.CombinatorAttribute()]
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
public partial class ChannelMap
{

private System.Collections.Generic.IDictionary<string, RoomFixtures> _rooms;

/// <summary>
/// Specifies the collection of light channel maps for all rooms.
/// </summary>
[System.Xml.Serialization.XmlIgnoreAttribute()]
[YamlDotNet.Serialization.YamlMemberAttribute(Alias="rooms")]
[System.ComponentModel.DescriptionAttribute("Specifies the collection of light channel maps for all rooms.")]
public System.Collections.Generic.IDictionary<string, RoomFixtures> Rooms
{
get
{
return _rooms;
}
set
{
_rooms = value;
}
}

public System.IObservable<ChannelMap> Process()
{
return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(
new ChannelMap
{
Rooms = _rooms
}));
}
}


/// <summary>
/// Serializes a sequence of data model objects into YAML strings.
/// </summary>
[Bonsai.CombinatorAttribute()]
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
[System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
public partial class SerializeToYaml
{

private System.IObservable<string> Process<T>(System.IObservable<T> source)
{
return System.Reactive.Linq.Observable.Defer(() =>
{
var serializer = new YamlDotNet.Serialization.SerializerBuilder().Build();
return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
});
}

public System.IObservable<string> Process(System.IObservable<RoomFixtures> source)
{
return Process<RoomFixtures>(source);
}

public System.IObservable<string> Process(System.IObservable<Fixture> source)
{
return Process<Fixture>(source);
}

public System.IObservable<string> Process(System.IObservable<ChannelMap> source)
{
return Process<ChannelMap>(source);
}
}


/// <summary>
/// Deserializes a sequence of YAML strings into data model objects.
/// </summary>
[System.ComponentModel.DefaultPropertyAttribute("Type")]
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<RoomFixtures>))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<Fixture>))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<ChannelMap>))]
[System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
{

public DeserializeFromYaml()
{
Type = new Bonsai.Expressions.TypeMapping<ChannelMap>();
}

public Bonsai.Expressions.TypeMapping Type { get; set; }

public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression> arguments)
{
var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
var returnType = typeMapping.GetType().GetGenericArguments()[0];
return System.Linq.Expressions.Expression.Call(
typeof(DeserializeFromYaml),
"Process",
new System.Type[] { returnType },
System.Linq.Enumerable.Single(arguments));
}

private static System.IObservable<T> Process<T>(System.IObservable<string> source)
{
return System.Reactive.Linq.Observable.Defer(() =>
{
var serializer = new YamlDotNet.Serialization.DeserializerBuilder().Build();
return System.Reactive.Linq.Observable.Select(source, value =>
{
var reader = new System.IO.StringReader(value);
var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
return serializer.Deserialize<T>(parser);
});
});
}
}
}
Loading

0 comments on commit 74d169d

Please sign in to comment.