Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix load_morpholgies to always resolve paths #1047

Merged
merged 8 commits into from
Jun 16, 2022

Conversation

eleftherioszisis
Copy link
Contributor

@eleftherioszisis eleftherioszisis commented Jun 13, 2022

Issue: If a relative morphology directory is passed into neurom.load_morphologies, a Population object is created with relative paths to the morphologies. If the directory is changed after the Population is created, the paths will not be valid anymore.
Changes: Population makes paths absolute. Note that it does not resolve symlinks.
Fixes #1046

Copy link
Member

@adrien-berchet adrien-berchet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if the path resolution should not be located in the Population constructor? Because creating a new Population instance will still have the same issue if the user does not use the load_morphologies function.

tests/io/test_io_utils.py Outdated Show resolved Hide resolved
Co-authored-by: Adrien Berchet <adrien.berchet@gmail.com>
@codecov-commenter
Copy link

codecov-commenter commented Jun 13, 2022

Codecov Report

❗ No coverage uploaded for pull request base (v4@94f79e5). Click here to learn what that means.
The diff coverage is n/a.

@@          Coverage Diff           @@
##             v4     #1047   +/-   ##
======================================
  Coverage      ?   100.00%           
======================================
  Files         ?        35           
  Lines         ?      2475           
  Branches      ?         0           
======================================
  Hits          ?      2475           
  Misses        ?         0           
  Partials      ?         0           

@eleftherioszisis
Copy link
Contributor Author

I am wondering if the path resolution should not be located in the Population constructor? Because creating a new Population instance will still have the same issue if the user does not use the load_morphologies function.

I am not so much in favor for the Population to do io stuff, as it is not its job.

@adrien-berchet
Copy link
Member

I am not so much in favor for the Population to do io stuff, as it is not its job.

But it already does, isn't it? If the cache is disabled, only file paths are stored in the Population object.

@eleftherioszisis
Copy link
Contributor Author

I am not so much in favor for the Population to do io stuff, as it is not its job.

But it already does, isn't it? If the cache is disabled, only file paths are stored in the Population object.

Well, yeah but my issue is that it can take either files or morphologies as the first argument. However, for the resolution to be correct, it cannot be lazy, because the directory can be changed at any time after init, before calling the iterators. So for this to work on the population, I would need to add a line that checks all files if they are morphologies or paths and then resolve them as needed, before letting cache and the rest do their own thing.

I would be more willing to add an assertion in Population._load_file for the path to be absolute. However, this is limiting if someone wants to create intentionally a population from relative paths.

@adrien-berchet
Copy link
Member

Yeah, I prefer the first solution (resolving before the cache and other stuffs) because it makes it more consistent. But I agree that it would be cleaner to have a constructor that only accept a list of morphologies so the paths can be processed elsewhere but this would induce breaking changes. So as you prefer :-)

@eleftherioszisis
Copy link
Contributor Author

eleftherioszisis commented Jun 14, 2022

Unfortunately, I cannot make Population fully resolve the paths, because there are test cases that use symlinks to morphologies with different filename...

Therefore paths are made absolute, but they are not resolved, which means that neither symlinks are resolved nor dot paths e.g. "..".

Edit: I have ended up resolving the parent, but not the full path. This works with the symlinked files and resolves any relative path or symlinks in the parent path.

@adrien-berchet
Copy link
Member

I don't get what's the issue with symlinks to morphologies with different filename? Is it because the tests check the file names?

@eleftherioszisis
Copy link
Contributor Author

I don't get what's the issue with symlinks to morphologies with different filename? Is it because the tests check the file names?

According to the test:

def test_load_morphologies_filenames():
pop = utils.load_morphologies(FILENAMES, name='test123')
assert len(pop) == 2
assert pop.name == 'test123'
for m, name in zip(pop.morphologies, NRN_NAMES):
assert isinstance(m, Morphology)
assert m.name == name

The name of the morphology should be the name of the file that is passed. If the symlink uses a different name and the path is resolved, that name will be lost to the name of the file it points to.

@adrien-berchet
Copy link
Member

Hmmm ok
Is it really a feature (having morphology names of the population equal to the unresolved file name) or is it just something we check to be sure the test passed (in this case we could just change how we check this test)?

@eleftherioszisis
Copy link
Contributor Author

Hmmm ok Is it really a feature (having morphology names of the population equal to the unresolved file name) or is it just something we check to be sure the test passed (in this case we could just change how we check this test)?

No idea. I find it strange, but maybe it was a use case in the past.
https://github.com/BlueBrain/NeuroM/tree/master/tests/data/valid_set

@adrien-berchet
Copy link
Member

Maybe. Anyway, I guess resolving the parent only is ok, though it might still result in very surprising behavior in some very specific cases. E.g. if there is a symlink in the given path and this symlink is changed during runtime (which is very unlikely ofc), the result will be different if the symlink is in the parents or if it is the actual target.

CHANGELOG.rst Outdated Show resolved Hide resolved
@eleftherioszisis eleftherioszisis merged commit 2ff9737 into v4 Jun 16, 2022
@eleftherioszisis eleftherioszisis deleted the zisis/fix-load-morphologies branch June 16, 2022 08:42
@adrien-berchet adrien-berchet added this to the v4 milestone Feb 22, 2023
eleftherioszisis pushed a commit that referenced this pull request May 14, 2024
* Mixed subtree processing (#981)
* Refactor tests for test_mixed.py (#1027)
* Remove deprecated modules and functions/classes & warnings (#1026, #1032)
* Use readonly morphio Morphology by default (#979)
* Morphology level radial distance features use the soma as reference point (#1030)
* Expose subtree processing from the morph_stats api (#1034)
* Remove pyXX prefix for lint, docs, and coverage (#1038)
* Fix tutorials and add tutorial testenv (#1039)
* Add isort for formatting/linting (#1040)
* Add testing of example scripts (#1041)
* Make documentation/docstrings testable (#1035)
* Add black to neurom, format everything, and add to lint (#1042)
* Fix load_morpholgies to always resolve paths (#1047)
* allow Morphology objects to be either mut or immut (#1049)
* Replace iter_* methods by properties in core objects and improve iter_segments (#1054)
* Decouple Morphology constructor from io (#1120)
* Move soma methods to functions (#1118)
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.

4 participants