Skip to content

Conversation

tlambert03
Copy link
Contributor

@tlambert03 tlambert03 commented Jul 2, 2025

One possible solution to #679

This would allow us to double check that all state devices implement a uniform interface (i.e. they all have both 'State' and 'Label' properties)

just a thought, curious what @nicost and @marktsuchida think (not married to it of course... just an idea)

@tlambert03
Copy link
Contributor Author

For example...

Before this PR (demo configuration):

# Labels
Label,Dichroic,0,400DCLP
Label,Dichroic,1,Q505LP
Label,Dichroic,2,Q585LP
Label,Dichroic,3,89402bs
Label,Dichroic,4,State-4
Label,Dichroic,5,State-5
Label,Dichroic,6,State-6
Label,Dichroic,7,State-7
Label,Dichroic,8,State-8
Label,Dichroic,9,State-9
Label,Emission,0,Chroma-HQ620
Label,Emission,1,Chroma-D460
Label,Emission,2,Chroma-HQ535
Label,Emission,3,Chroma-HQ700
Label,Emission,4,89402m
Label,Emission,5,State-5
Label,Emission,6,State-6
Label,Emission,7,State-7
Label,Emission,8,State-8
Label,Emission,9,State-9
Label,Excitation,0,Chroma-D360
Label,Excitation,1,Chroma-HQ480
Label,Excitation,2,Chroma-HQ570
Label,Excitation,3,Chroma-HQ620
Label,Excitation,4,State-4
Label,Excitation,5,State-5
Label,Excitation,6,State-6
Label,Excitation,7,State-7
Label,Excitation,8,State-8
Label,Excitation,9,Empty
Label,Objective,0,Nikon 40X Plan Fluor ELWD
Label,Objective,1,Nikon 10X S Fluor
Label,Objective,2,Objective-2
Label,Objective,3,Nikon 20X Plan Fluor ELWD
Label,Objective,4,Objective-4
Label,Objective,5,Objective-5
Label,Path,0,State-0
Label,Path,1,State-1
Label,Path,2,State-2
Label,LED,0,Closed
Label,LED,1,385nm
Label,LED,2,470nm
Label,LED,3,550nm
Label,LED,4,635nm
Label,LED,5,State-5
Label,LED,6,State-6
Label,LED,7,State-7
Label,LED,8,State-8
Label,LED,9,State-9

After this PR

# Labels
Label,Dichroic,0,400DCLP
Label,Dichroic,1,Q505LP
Label,Dichroic,2,Q585LP
Label,Dichroic,3,89402bs
Label,Emission,0,Chroma-HQ620
Label,Emission,1,Chroma-D460
Label,Emission,2,Chroma-HQ535
Label,Emission,3,Chroma-HQ700
Label,Emission,4,89402m
Label,Excitation,0,Chroma-D360
Label,Excitation,1,Chroma-HQ480
Label,Excitation,2,Chroma-HQ570
Label,Excitation,3,Chroma-HQ620
Label,Excitation,9,Empty
Label,Objective,0,Nikon 40X Plan Fluor ELWD
Label,Objective,1,Nikon 10X S Fluor
Label,Objective,2,Objective-2
Label,Objective,3,Nikon 20X Plan Fluor ELWD
Label,Objective,4,Objective-4
Label,Objective,5,Objective-5
Label,LED,0,Closed
Label,LED,1,385nm
Label,LED,2,470nm
Label,LED,3,550nm
Label,LED,4,635nm

@marktsuchida
Copy link
Member

The question I have is how this interacts with devices (mostly motorized stands) that auto-detect their components (objectives, filter cubes, condensers, light-path positions, etc.) and auto-populate the labels. It feels a bit fragile to not record those. I'm not 100% sure that it would be a problem, but also not immediately confident that it wouldn't be a problem.

@tlambert03
Copy link
Contributor Author

Ah... because that auto population happens after Initialize()? Can you point me to an adapter like that?

@tlambert03
Copy link
Contributor Author

tlambert03 commented Jul 2, 2025

So, I wrote a little script and it looks like the only call to SetPositionLabel that does not come inside of an Initialize() method is in TofraFilterWheel::OnNumPos... So that's safe

So, I guess the case we should potentially be concerned about is one where:

  • on one launch, the device auto-detection completes successfully
  • on a later launch, the device auto-detection fails, but the labels from the previous autodetection was indeed still valid

currently, that very first autodetection would have permanently set those detected labels in the config.
On this PR, they would not get written to the config, and future auto-detections would have the ability to change those labels. (honestly... could sometimes be a good thing?)

We could always add an option that:

  • allows the user to force the labels to be written to the config even if they are default labels
  • (an elaboration) sets a default/user-editable threshold for when the defaults should be written... i.e. if there are less than N labels

@marktsuchida
Copy link
Member

Ah... because that auto population happens after Initialize()? Can you point me to an adapter like that?

I think the auto-population happens during initialization; an example is ZeissCAN29, for example the objective turret. So logically there would be no problem -- if nothing changes over time.

But things do change over time. One possibility is that the device adapter or driver decides to report a slightly different string (like "63x 1.4NA" instead of "63x NA1.4"). That would break any config groups referencing the state device's Label property. Perhaps this should be considered a rare situation and in any case the bug is in the adapter/driver.

The auto-detected labels could also change due to the microscopist actually swapping (or reordering) the components. If the labels are fixed in the config file, then the configuration would still be functional, albeit mislabeled. The labels can be edited in the HCW (I don't remember of config groups containing Label get automatically updated in this case, but conceivably they could be).

But if the labels are not stored in the HCW, then the config would be broken on loading and at least those config groups woul d need to be recreated from scratch to fix it.

I guess one "safe" workaround would be to omit the labels from the config file only when they are not only equal to default but also numerous (say, >100 states) -- though a messy heuristic.

@tlambert03
Copy link
Contributor Author

One possibility is that the device adapter or driver decides to report a slightly different string (like "63x 1.4NA" instead of "63x NA1.4"). That would break any config groups referencing the state device's Label property.

we could also ensure that there are no implicit labels included in config groups. If a label is referenced in a config group, it would always be included in the labels section of a config

If the labels are fixed in the config file, then the configuration would still be functional, albeit mislabeled

you're referring again to the case where one of those labels is referenced elsewhere in the config file right? Like a config group? I do think it would be best to "pin" any labels used elsewhere in the config, even if they are default labels.

... beyond that case of referencing an (implicit) default label elsewhere in the config file, are there other cases you can think of?

@marktsuchida
Copy link
Member

we could also ensure that there are no implicit labels included in config groups. If a label is referenced in a config group, it would always be included in the labels section of a config

That seems like an excellent idea!

I also confirmed that all existing calls to DeviceBase's SetPositionLabel() occur during Initialize().

The other thing is.... We need to do this to the MMStudio and pymmcore-plus implementations of config saving, because saveSystemConfiguration is not actually used (maybe CMMCore gains a function to get the list of non-default labels). In addition, we need to see how the label config UI does with the 64k rows, even if not saved. But I like the general direction!

@nicost
Copy link
Member

nicost commented Sep 25, 2025

This looks so promising. I I understand correctly, the outstanding work is:

  • Ensure that there are no implicit labels included in config groups. If a label is referenced in a config group, it would always be included in the labels section of a config.
  • Fix MMStudio and pymmcore-plus implementations of config saving to include "implicit" labels that are used in config groups into the labels section.
    Is that correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants