0hughman0 / cassini Goto Github PK
View Code? Open in Web Editor NEWTurn Jupyter Lab with Python into an electronic lab notebook (ELN)
Home Page: https://0hughman0.github.io/Cassini/latest/quickstart.html
License: GNU General Public License v3.0
Turn Jupyter Lab with Python into an electronic lab notebook (ELN)
Home Page: https://0hughman0.github.io/Cassini/latest/quickstart.html
License: GNU General Public License v3.0
Current started time is only the date. This means sort by started is a bit dodgy.
Project needs a logo.
I was thinking something like a conical flask maybe with a >_
input prompt or something in it. idk
If you insert non JSON data into a meta dict, everything freaks out because whenever meta tries to write to disk, it can't.
We should verify something is serialisable prior to insertion.
Currently TierBase represents a broad range of tiers.
DataSets don't have notebooks, therefore templates and meta and highlights etc.
TierBase should be split into two Base classes - FolderTierBase and NotebookTierBase.
A FolderTier is one with no notebook.
A NotebookTier is one with notebook, meta highlights etc.
This stops dodgy null implementations of the Notebook methods for DataSets.
It should be straightforward to incorporate is instance checks into the code and also into the jl_cassini_server. Providing a type would probably be very useful and a solution to poor handling of the top and bottom of the hierarchy by jl_cassini.
Means if the project_folder is set to a symlink, this gets undone upon initialisation, which seems to cause problems generating relative paths because drives are different
Might be better to change to path.absolute()
, although not sure if there was a good reason to use resolve()
in the first place.
dirty workaround is:
# project.py
from pathlib import Path
project = Project(HIERARCHY, project_folder='P:/PhD')
project.project_folder = Path('P:/PhD') # explicitly set again, before launch
Datasets have no templates.
Default setup doesn't create a template folder, so this method raises an exception.
It is currently possible to get JupyterDesktop to work with Cassini, but this is not documented.
JupyterDesktop cannot be launched using project.launch()
therefore the server cannot be started by the same interpreter as the project object, which is how this is explicitly provided usually.
Instead, the implementation found here facilitates the use of a CASSINI_PROJECT
environment variable, that points the jupyter_cassini_server
to the right module and object within that module to allow the project
to be imported.
This means the PYTHONPATH
would also need to be patched to include the project.py
directory.
This needs to be added to the documentation.
There is an issue discussing related stuff on the JupyterLab extension side here.
like dict.items()
, but meta.items()
.
I need it.
Currently only data that can get served to the JLGui... and therefore can be rendered in the children table are meta.
It would be extremely cool to allow more arbitrary attributes to appear in this table. This could also be a way of setting what appears by default in the table.
Potential implementation:
# project.py
class MyTier(BaseTier):
__cassini_table_attrs__ = ['cookies']
@property
def cookies(self):
return 'yummy'
Then in the server
data = _serialise_tier(data)
for attr in tier.__cassini_table_attrs__:
data[attr] = getattr(tier, attr)
For example I found it useful to have a list of a samples datasets in the children_df.
This could be a more general way of allowing that:
class MySample(BaseTier):
@cassini_table_attr
@property
def techniques(self):
return [dset.name for dset in self]
This probably should live in the jupyer_cassini_server
extension.
Perhaps we even move the jlgui.extend_project
there and then have extend_project
inject techniques
as a starting point.
Currently, what I'm trying to do is:
We have a branch for each minor version e.g. 0.1.x
and 0.2.x
, the head of which should always be the latest patch of that minor release.
For development, I think we specify the whole planned version number, but add -pre
for pre-release e.g. 0.2.4-pre
.
We then create branches for implementing specific features, and submit PRs into those pre-release branches as progress is made.
If necessary, we publish a pre-release version, but within pyproject.toml
will have to use the poetry spec:
https://python-poetry.org/docs/cli/#version
e.g. the version would be something like 0.2.4a0
for the first pre-release.
Once we are happy with the pre-release, it can be merged (via PR) into the appropriate minor version branch and the pre-release branch can be deleted.
With the creation of jl_gui, I don't think child_df is strictly necessary anymore, as this was mostly used for the ipygui.
ipygui could maybe be moved out too.
Only concern is this would make things harder to maintain...
We should add a run of jupyter_cassini
's unit tests, I guess just of the Python side, with each merge to avoid making breaking changes.
Because the hierarchy cannot be nested all objects at each level need to have the same implementation.
This is fine, except sometimes a Sample in one Experiment may require some very different functionality in another.
One could add additional methods in their project.py, but this leaves the class definition a bit cluttered and unsafe.
One solution would be to add an attribute like spec
short for specialist.
We then add a spec
decorator that looks something like:
class MySample(Sample):
...
@spec(['2', '1'])
def specialised_method(self, *args, **kwargs):
...
The arguments to spec would specify which ids are allowed access to this method. This could even do fancy Regex things.
Then through some internal magic:
>>> smpl = project['WP2.1c']
>>> help(smpl.spec)
...
Docs for some specialised class with specialised method.
...
Something along these lines.
Alternitve implementations I'm sure would be possible.
There's some incredibly flaky issue with the way type checking for protocols takes place, where it gets class attributes, which triggers an assertion error:
> conda create -n t python=3.8
> conda activate t
> pip install cassini
> python -c "from cassini import TierBase"
File "C:\ProgramData\Anaconda3\envs\t\lib\site-packages\cassini\core.py", line 147, in <module>
class TierBase(Protocol):
File "C:\ProgramData\Anaconda3\envs\t\lib\site-packages\typing_extensions.py", line 640, in __init__
cls.__callable_proto_members_only__ = all(
File "C:\ProgramData\Anaconda3\envs\t\lib\site-packages\typing_extensions.py", line 641, in <genexpr>
callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
File "C:\ProgramData\Anaconda3\envs\t\lib\site-packages\cassini\accessors.py", line 190, in __get__
val = self.func(owner)
File "C:\ProgramData\Anaconda3\envs\t\lib\site-packages\cassini\core.py", line 248, in child_cls
assert env.project
AssertionError
But what's really odd, is this only happens once. So re-running python -c "from cassini import TierBase"
will work the second time!
Seemingly there is a caching process that only runs once.
This might only be the case for Python3.8, or where this getattr
is called.
One solution is to change:
assert env.project
to
if not env.project
return None
for both child_cls
and parent_cls
, these still satisfy their types. I think these accessors are edge cases that haven't been thought of in the Protocol codebase.
For notebooks relying on cassini to do things like fetch data, one certainly can't share this notebook with another user who doesn't have cassini installed.
In the case they do have cassini installed, unless things are configured identically between users, notebooks will not run correctly.
I think adding something like:
# smpl = project.env('WP1.1a')
smpl = project.share('WP1.1a')
I.e. to share you swap these lines over.
At that point I'm not completely sure what to do...
There needs to be some way of freezing the appropriate paths at the point project.share
is called. For example adding metadata to the notebook file, which would probably be a mapping from children to relative paths.
The accessors continue to cause chaos.
Sphinx autodoc doesn't manage to generate docstrings for any CachedClassProps, presumably because it just gets those attributes from the class, which get returned as the cached value.
This means things like TierBase.name_part_template
are missing from the docs - they're important!
A solution may be found add some sort of preprocessor or whatever to Sphinx:
https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#event-autodoc-process-docstring
The CachedClassProps can be fetch from the classes using the syntax (which bypasses the accessor protocol):
>>> TierBase.__dict__['name_part_template']
CachedClassProp
and it seems the wraps is passing on the correct docstring. So it should be possible to generate the docstring I think, provided we can find a way to get the right object to Sphinx.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.