Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8a21268
starting in on UserLibrary
Mar 24, 2026
f75e48d
starting in on UserLibrary
Mar 24, 2026
73963ea
Merge branch 'asset-switch' into user-library-rework
Mar 25, 2026
7760a46
Merge branch 'asset-switch' into user-library-rework
Mar 26, 2026
c868d26
adding logical structures for bulk export
Apr 1, 2026
9ab34d8
Merge branch 'asset-switch' into user-library-rework
Apr 1, 2026
c0dd39f
live adding to library seems to work
Apr 1, 2026
27ff661
fixed deprecated popup controls, export now zips and shares as one wo…
Apr 1, 2026
8e2a737
library import theoretically works (needs testing)
Apr 2, 2026
ac3b992
Merge branch 'asset-switch' into user-library-rework
Apr 2, 2026
84ae49d
added library export as zip and revised import to allow zip import
Apr 7, 2026
ecbe17e
Merge branch 'asset-switch' into user-library-rework
Apr 8, 2026
ff377d0
Merge branch 'asset-switch' into user-library-rework
Apr 8, 2026
4a60a4f
added laser firing indicator on top of graph
Apr 8, 2026
e58c614
added indicators for battery too low to acquire, started new metadata…
Apr 9, 2026
803f82d
[0.9.57] improved user library control, laser warning feedback, built…
Apr 9, 2026
ae6f837
[0.9.58] tradeshow build, BLE low signal effectively removed
Apr 10, 2026
89c3fd5
Merge branch 'asset-switch' into user-library-rework
Apr 21, 2026
3fe80af
[0.9.59] fixed 99 percent of app theming
Apr 21, 2026
b39c51f
fixed styling for radio button
Apr 22, 2026
29543a2
improved entry styling marginally
Apr 22, 2026
fd26660
entry styling fixed using android themes
Apr 22, 2026
1f28ace
[0.9.60] finished style consistency fixes
Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AppShell.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:EnlightenMAUI"
Shell.FlyoutBehavior="Disabled"
Shell.TabBarBackgroundColor="#333"
Shell.TabBarForegroundColor="#EEE"
Shell.TabBarDisabledColor="#555"
Shell.TabBarUnselectedColor="#BBB"
Shell.TabBarTitleColor="#EEE"
Title="EnlightenMAUI">

<Shell.BindingContext>
Expand Down
12 changes: 8 additions & 4 deletions EnlightenMAUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android34.0|AnyCPU'">
<IsPublishable>False</IsPublishable>
<ApplicationDisplayVersion>0.9.56</ApplicationDisplayVersion>
<ApplicationDisplayVersion>0.9.60</ApplicationDisplayVersion>
<ApplicationTitle>EnlightenMobile</ApplicationTitle>
<DefineConstants>$(DefineConstants);USE_DECON</DefineConstants>
<AndroidStoreUncompressedFileExtensions>.so</AndroidStoreUncompressedFileExtensions>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-android34.0|AnyCPU'">
<IsPublishable>False</IsPublishable>
<ApplicationDisplayVersion>0.9.56</ApplicationDisplayVersion>
<ApplicationDisplayVersion>0.9.60</ApplicationDisplayVersion>
<ApplicationTitle>EnlightenMobile</ApplicationTitle>
<AndroidPackageFormat>apk</AndroidPackageFormat>
<AndroidStoreUncompressedFileExtensions>.so</AndroidStoreUncompressedFileExtensions>
Expand Down Expand Up @@ -92,6 +92,8 @@
<ItemGroup>
<None Remove="appsettings.json" />
<None Remove="libdpSTJE.so" />
<None Remove="Platforms\Android\Resources\values-night\styles.xml" />
<None Remove="Platforms\Android\Resources\values\styles.xml" />
<None Remove="Platforms\Android\Resources\xml\device_filter.xml" />
<None Remove="Stj.ProtectionSdk.so" />
<None Remove="Resources\AppIcon\appicon.svg" />
Expand Down Expand Up @@ -185,6 +187,9 @@
<MauiXaml Update="Popups\AddToLibraryPopup.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Popups\ExportPopup.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Popups\OverlaysPopup.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
Expand Down Expand Up @@ -214,14 +219,13 @@

<ItemGroup>
<Folder Include="Processing\library\" />
<Folder Include="Processing\ml\" />
</ItemGroup>

<ItemGroup Condition="Exists('..\EMAUIHelpers\models')">
<MauiAsset Include="..\EMAUIHelpers\models\nrd-d2-r53-model-12-opset18\background_model.onnx" Link="Processing\ml\background_model.onnx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</MauiAsset>
<MauiAsset Include="..\EMAUIHelpers\models\nrd5-r3-model-17-opset18\background_model_light.onnx" Link="Processing\ml\background_model_light.onnx">
<MauiAsset Include="..\EMAUIHelpers\models\nrd5-r3-model-17-opset18\r3-model-17-light.onnx" Link="Processing\ml\r3-model-17-light.onnx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</MauiAsset>
</ItemGroup>
Expand Down
49 changes: 49 additions & 0 deletions MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
using EnlightenMAUI.Models;
using System.Reflection;
using Telerik.Maui.Controls.Compatibility;
using Android.Content.Res;

#if ANDROID
using AndroidX.AppCompat.Widget;
#endif

namespace EnlightenMAUI;

Expand Down Expand Up @@ -38,6 +43,50 @@ public static MauiApp CreateMauiApp()

builder.Services.AddTransient<AppShell>();

Microsoft.Maui.Handlers.RadioButtonHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
#if ANDROID
if (handler.PlatformView is Android.Widget.RadioButton radioButton)
{
var states = new int[][]
{
new int[] { Android.Resource.Attribute.StateChecked },
new int[] { -Android.Resource.Attribute.StateChecked }
};

// Define the colors corresponding to the states (border color)
var colors = new int[]
{
new Android.Graphics.Color(0x27, 0xc0, 0xa1),
new Android.Graphics.Color(0x27, 0xc0, 0xa1)
};

// Create a ColorStateList with the states and colors
var colorStateList = new Android.Content.Res.ColorStateList(states, colors);

// Apply the color tint to the button's border
radioButton.ButtonTintList = colorStateList;
}
#endif
});

/*
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
#if ANDROID
//handler.PlatformView.BorderStyle = Android.Graphics.Color.White;
var pv = handler.PlatformView;
if (pv is AppCompatEditText editText)
{
editText.Background?.Mutate();
var color = new Android.Graphics.Color(0x27, 0xc0, 0xa1);
var hintColor = new Android.Graphics.Color(0xBB, 0xBB, 0xBB);
editText.BackgroundTintList = ColorStateList.ValueOf(Android.Graphics.Color.Transparent);
//editText.SetHintTextColor(hintColor);
}
#endif
});
*/

#if DEBUG
builder.Logging.AddDebug();
Expand Down
7 changes: 4 additions & 3 deletions Models/API6BLESpectrometer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ public async Task updateRSSI()
logger.debug("current RSSI {0}", rssi);
NotifyPropertyChanged("rssi");
await Task.Delay(500);
if (rssi < -90)
if (rssi < -105)
{
++badSignalCount;

Expand Down Expand Up @@ -845,15 +845,16 @@ public override async Task<bool> takeOneAveragedAsync()
stretchedDark = new double[smoothed.Length];
measurement.dark = stretchedDark;
measurement.postProcessed = smoothed;
measurement.processingMethod = "Noise and Background Removal";
measurement.processingMethod = PlatformUtil.modelName;
}
else
{
double[] staticWavenumbers = Enumerable.Range(400, 2008).Select(x => (double)x).ToArray();
double[] newIntensities = Wavecal.mapWavenumbers(wavenumbers, measurement.processed, staticWavenumbers);
measurement.wavenumbers = staticWavenumbers;
measurement.postProcessed = newIntensities;
}
measurement.processingMethod = "";
}

////////////////////////////////////////////////////////////////////////
// Store Measurement
Expand Down
7 changes: 4 additions & 3 deletions Models/API9BLESpectrometer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,7 @@ public async Task updateRSSI()
logger.debug("current RSSI {0}", rssi);
NotifyPropertyChanged("rssi");
await Task.Delay(500);
if (rssi < -90)
if (rssi < -105)
{
++badSignalCount;

Expand Down Expand Up @@ -1322,15 +1322,16 @@ public override async Task<bool> takeOneAveragedAsync()
measurement.rawDark = dark;
measurement.dark = stretchedDark;
measurement.postProcessed = smoothed;
measurement.processingMethod = "Noise and Background Removal";
measurement.processingMethod = PlatformUtil.modelName;
}
else
{
double[] staticWavenumbers = Enumerable.Range(400, 2008).Select(x => (double)x).ToArray();
double[] newIntensities = Wavecal.mapWavenumbers(wavenumbers, measurement.processed, staticWavenumbers);
measurement.wavenumbers = staticWavenumbers;
measurement.postProcessed = newIntensities;
}
measurement.processingMethod = "";
}

////////////////////////////////////////////////////////////////////////
// Store Measurement
Expand Down
5 changes: 3 additions & 2 deletions Models/BluetoothSpectrometer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ public async Task updateRSSI()
logger.debug("current RSSI {0}", rssi);
NotifyPropertyChanged("rssi");
await Task.Delay(500);
if (rssi < -90)
if (rssi < -105)
{
++badSignalCount;

Expand Down Expand Up @@ -1373,14 +1373,15 @@ public override async Task<bool> takeOneAveragedAsync()
measurement.rawDark = dark;
measurement.dark = stretchedDark;
measurement.postProcessed = smoothed;
measurement.processingMethod = "Noise and Background Removal";
measurement.processingMethod = PlatformUtil.modelName;
}
else
{
double[] staticWavenumbers = Enumerable.Range(400, 2008).Select(x => (double)x).ToArray();
double[] newIntensities = Wavecal.mapWavenumbers(wavenumbers, measurement.processed, staticWavenumbers);
measurement.wavenumbers = staticWavenumbers;
measurement.postProcessed = newIntensities;
measurement.processingMethod = "";
}

////////////////////////////////////////////////////////////////////////
Expand Down
33 changes: 27 additions & 6 deletions Models/Measurement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
namespace EnlightenMAUI.Models;


public class AgnosticSimpleMeasurement
{
public Tuple<List<double>, List<double>> data;
public Dictionary<string, string> metadata;
}

public class spectrumJSON
{
public string id;
Expand Down Expand Up @@ -225,7 +231,7 @@ public double[] postProcessed
public double excitationNM { get; set; }
public float[] wavecalCoeffs { get; set; }
public double? laserPower { get; set; }
public string processingMethod { get; set; } = "Wavenumber Interpolation Only";
public string processingMethod { get; set; } = "";

////////////////////////////////////////////////////////////////////////
// Methods
Expand Down Expand Up @@ -559,7 +565,7 @@ public void postProcess()
/// - support full ENLIGHTEN metadata
/// - support SaveOptions (selectable output fields)
/// </todo>
public async Task<bool> saveAsync(bool librarySave = false, bool autoSave = false)
public async Task<bool> saveAsync(bool librarySave = false, bool autoSave = false, bool forceWrite = false, Dictionary<string, string> forcedMetadata = null)
{
logger.debug("Measurement.saveAsync: starting");

Expand All @@ -584,7 +590,7 @@ public async Task<bool> saveAsync(bool librarySave = false, bool autoSave = fals
return true;
}

if (processed is null || raw is null || spec is null)
if ((processed is null || raw is null || spec is null) && !forceWrite)
{
logger.error("saveAsync: nothing to save");
return false;
Expand All @@ -593,9 +599,15 @@ public async Task<bool> saveAsync(bool librarySave = false, bool autoSave = fals
pathname = Path.Join(savePath, filename);
logger.debug($"Measurement.saveAsync: creating {pathname}");

UserLibrary ul = UserLibrary.getInstance();
ul.addSpectrum(this, PlatformUtil.getFileName(filename));

using (StreamWriter sw = new StreamWriter(pathname))
{
writeMetadata(sw);
if (forcedMetadata != null)
writeMetadata(sw, forcedMetadata);
else if (spec != null)
writeMetadata(sw);
sw.WriteLine();
writeSpectra(sw, librarySave);
}
Expand Down Expand Up @@ -656,7 +668,8 @@ void writeMetadata(StreamWriter sw)
sw.WriteLine("Laser Wavelength, {0}", spec.eeprom.laserExcitationWavelengthNMFloat);
sw.WriteLine("Timestamp, {0}", timestamp.ToString("dd/MM/yyyy HH:mm:ss.fff"));
sw.WriteLine("Library Used, {0}", libraryUsed);
sw.WriteLine("Processing Method, {0}", spec.measurement.processingMethod);
sw.WriteLine("DalaiRamanID.DALAI Enabled, {0}", spec.measurement.processingMethod.Length > 0);
sw.WriteLine("DalaiRamanID.DALAI Model, {0}", spec.measurement.processingMethod);
if (spec.measurement.declaredScore.HasValue)
{
if (spec.measurement.declaredMatch.Length > 0)
Expand All @@ -680,7 +693,15 @@ void writeMetadata(StreamWriter sw)
sw.WriteLine("QR Scan, {0}", spec.qrValue);
sw.WriteLine("Host Description, {0}", settings.hostDescription);
if (location != null)
sw.WriteLine("Location, lat {0}, lon {1}", location.Latitude, location.Longitude);
sw.WriteLine("Location, lat {0} : lon {1}", location.Latitude, location.Longitude);
}

void writeMetadata(StreamWriter sw, Dictionary<string,string> metadata)
{
foreach (string key in metadata.Keys)
{
sw.WriteLine($"{key},{metadata[key]}");
}
}

string render(double[] a, int index, string format = "f2")
Expand Down
2 changes: 1 addition & 1 deletion Models/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public bool autoRetry
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(autoRetry)));
}
}
bool _autoRetry = true;
bool _autoRetry = false;


public string getSavePath()
Expand Down
3 changes: 2 additions & 1 deletion Models/USBSpectrometer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -526,14 +526,15 @@ public override async Task<bool> takeOneAveragedAsync()
measurement.rawDark = dark;
measurement.dark = stretchedDark;
measurement.postProcessed = smoothed;
measurement.processingMethod = "Noise and Background Removal";
measurement.processingMethod = PlatformUtil.modelName;
}
else
{
double[] staticWavenumbers = Enumerable.Range(400, 2008).Select(x => (double)x).ToArray();
double[] newIntensities = Wavecal.mapWavenumbers(wavenumbers, measurement.processed, staticWavenumbers);
measurement.wavenumbers = staticWavenumbers;
measurement.postProcessed = newIntensities;
measurement.processingMethod = "";
}

////////////////////////////////////////////////////////////////////////
Expand Down
62 changes: 62 additions & 0 deletions Models/UserLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using EnlightenMAUI.Platforms;
using System;
using System.Collections.Generic;
using System.Text;

namespace EnlightenMAUI.Models
{
internal class UserLibrary
{
static UserLibrary instance = null;

Settings settings = Settings.getInstance();
public Dictionary<string, string> userSpectra = new Dictionary<string, string>();
public List<string> userSpectraKeys
{
get
{
return new List<string>(userSpectra.Keys);
}
}

static public UserLibrary getInstance()
{
if (instance == null)
instance = new UserLibrary();

return instance;
}

public UserLibrary()
{
loadTodaySpectra();
}

public async Task loadTodaySpectra()
{
Dictionary<string, Measurement> library = new Dictionary<string, Measurement>();
Dictionary<string, double[]> originalRaws = new Dictionary<string, double[]>();
Dictionary<string, double[]> originalDarks = new Dictionary<string, double[]>();
string path = PlatformUtil.getAutoSavePath(true);
await PlatformUtil.loadFiles(useAssets: false, path, library, originalRaws, originalDarks, true, null, skipSearch: true);

foreach (string tag in library.Keys)
{
Measurement m = library[tag];
string userTag = $"{m.timestamp.ToString("HH:mm:ss")} {(m.declaredMatch != null && m.declaredMatch.Length > 0 ? m.declaredMatch[0] : "")} {(m.declaredScore.HasValue ? m.declaredScore.Value.ToString("f2") : "")}";
Logger.getInstance().debug("adding {0} to user library as {1}", userTag, tag);
userSpectra.Add(userTag, tag);
}
}

public void addSpectrum(Measurement m, string tag)
{
string userTag = $"{m.timestamp.ToString("HH:mm:ss")} {(m.declaredMatch != null && m.declaredMatch.Length > 0 ? m.declaredMatch[0] : "")} {(m.declaredScore.HasValue ? m.declaredScore.Value.ToString("f2") : "")}";
if (!userSpectra.ContainsKey(userTag))
{
Logger.getInstance().debug("adding {0} to user library as {1}", userTag, tag);
userSpectra.Add(userTag, tag);
}
}
}
}
Loading