Skip to content

feat(oak): rest-activity rhythm metrics (IS, IV, RA, cosinor) - #323

Open
ceyhunolcan wants to merge 9 commits into
onnela-lab:developfrom
ceyhunolcan:feat-oak-rest-activity-rhythms
Open

ceyhunolcan wants to merge 9 commits into
onnela-lab:developfrom
ceyhunolcan:feat-oak-rest-activity-rhythms

Conversation

@ceyhunolcan

Copy link
Copy Markdown
Contributor

Adds oak/rhythms.py: rest-activity rhythm summaries from accelerometer data interdaily stability (IS), intradaily variability (IV), relative amplitude (RA) with L5/M10, and a 24 h cosinor (MESOR, amplitude, acrophase, R²). Same raw accelerometer stream as the gait/step output, a different (24 h patterning) question. Activity is ENMO per epoch; run() mirrors oak.base.run.

Placement: a module inside oak rather than a new tree, since RAR is an accelerometer analysis. It writes its own output (recording-level rar_summary.csv, plus per-participant <backend_id>_rar_daily.csv at a daily frequency) rather than extending _gait_daily.csv, because IS/IV are recording-level while gait output is per-day.

Notes / open questions

  • Assumes accelerometer in g to match oak's min_amp; gravity param handles m/s².
  • Happy to fold into a standalone tree instead if you'd prefer.

Tests: tests/oak/test_rhythms.py ground-truth recovery (clean rhythm recovers acrophase/MESOR/amplitude, IS≈1; white noise → IS at 1/n_days, IV≈2; identical days → IS=1) + end to-end. ruff/flake8/mypy clean; full suite green.

Docs: docs/source/rhythms.md (+ toctree).

@biblicabeebli

Copy link
Copy Markdown
Member

(gotta stick this somewhere)
I need to add you to the contributers - what would you like for your name/attribution?

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Thanks, that's kind of you! For attribution:

Ceyhun Olcan
ORCID: 0000-0002-6326-6071

Affiliation (if the file takes one): Dartmouth College

Happy with whatever format fits your contributors file, name alone is fine if ORCID/affiliation don't fit the schema.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up: added tests for the time_start/time_end bounds and the min_valid_days skip path in run (the orchestration layer wasn't covered), and hardened run to always return a frame with a backend_id column when every participant is filtered out (previously it returned a column-less empty frame). Full suite green.

@biblicabeebli

Copy link
Copy Markdown
Member

(ok, I haven't gotten to a point where I can review this one yet)

@biblicabeebli
biblicabeebli changed the base branch from develop to ruff-check-reflow-and-typing July 30, 2026 17:31
@biblicabeebli

Copy link
Copy Markdown
Member

I did not realize this was an entirely new analysis, very cool.

Since there are no conflicts we could be ready to go, but with my work on the ruff.... branch I wanted to go through this in full, my process is to read the code, do my formatting changes, then I add that formatting commit to the git blame ignorer.

I'm currently doing this process on a new branch ceyhunolcan-feat-oak-rest-activity-rhythms that starts with a rebase on top of the ruff.... branch. This is not necessarily final work, don't close this pull.

Review for inclusion - I probably cannot just review and OK this, I will need to task someon on our end is qualified to do that type of review. @hydawo This is the work I mentioned.

Question: very roughly and non-rigorously, what is the performance like on this?

@biblicabeebli

Copy link
Copy Markdown
Member

Yo, I just pushed 8e2e124 on ceyhunolcan-feat-oak-rest-activity-rhythms which does the text width transformations and like 2 minor changes.

Tests pass.
ruff check passes
mypy does not pass

Why don't you do a sanity check? Then we can work out next step for some code review from me while we are working out the more academic code review.

I'll propose you reset your branch to be the state of my branch, and then we can review and maintain this pull request thread.

@biblicabeebli

Copy link
Copy Markdown
Member

update: it is this commit a225e2c

@ceyhunolcan

ceyhunolcan commented Jul 31, 2026 •

Copy link
Copy Markdown
Contributor Author

Done! Reset to match a225e2c and pushed. On the sanity check: the mypy failures were config/typing, not logic. After the mypy.ini → pyproject migration numba had no override (4 errors); added numba/numba.*. The other 2 were real once pandas is checked with stubs, _align_to_day_grid built its grid off activity.index typed as Index[Any], so .tz and the date_range overload didn't resolve; fixed by constructing a pd.DatetimeIndex. mypy (src + tests), ruff, and the oak suite are clean, and all three jobs are green on my fork's CI.

On performance: per participant, cost is dominated by reading and epoching the raw accelerometer CSVs, not the metrics. IS/IV/RA are single vectorized passes over the per-epoch vector and the cosinor is a 3-column least-squares, all linear in epochs, so a multi-week recording at 1-min epochs is well under a second of compute once loaded. I/O scales with study size; the math doesn't.

@biblicabeebli

Copy link
Copy Markdown
Member

mypy - mypy passes on the ruff-check-reflow-and-typing branch without modification, it did not involve numba.

Numba should not be added to the mypy ignore module.

Pandas should have been removed from that list and it is a bug that it was still present to begin with. I have now removed it in a commit on the ruff-check-reflow-and-typing branch. I think if you revert your commit there is no merge conflict.

I'm also going to need a statement from you on use of ai tooling here, we are developing an ai tool policy but don't have one yet.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Dropped the numba overrides so pyproject matches your ruff-check-reflow-and-typing config (no numba, no pandas; pandas type-checked strictly). The DatetimeIndex fix in _align_to_day_grid stays, since that's what makes rhythms.py pass under strict pandas typing. Should merge cleanly now.

On AI tooling: the substance of this work is my own. The rest-activity rhythm methods (IS, IV, RA, cosinor) come from a library I wrote and validated against real NHANES data before this PR and that's my prior research, not anything generated here. The engineering calls were mine as well: what to fix, what to leave alone, how to structure the tests, and how to respond to review.

I do use AI (Claude) in my workflow, mainly for drafting and thinking through options, but I direct it and verify everything it helps with for this PR that meant reproducing each issue myself, writing and running the tests, running the full ruff/mypy/pytest gauntlet locally, and confirming behaviour before pushing I don't submit anything I can't explain or haven't checked.

So the methods, the judgment, and the verification are mine, and I stand behind all of the code. I think transparency here is the right default, so I'm glad you're putting a policy together and happy to follow whatever the lab lands on.

@biblicabeebli

Copy link
Copy Markdown
Member

(been busy with other issues, putting in some time over here. I'll be back at work Tuesday, so no need for an instant turnaround.)

I had a colleague take a look at this pull request (academic perspective), I'm going to detail that and then respond to your comment and do further re-review.

Requests, Recommendations

  1. Add a minimum daily coverage criterion before counting valid days.
  • valid_days is based on total valid epochs, so partially observed days can be counted as complete days.
  • Consider applying min_valid_hours_per_day first and counting only sufficiently observed days toward min_valid_days.
  1. Clarify epoch_seconds vs. epochs_per_day.
  • epoch_seconds=60 means 1-minute epochs, while 86400 / 60 = 1440 is the number of epochs per 24-hour day.
  • Make this clearer in the documentation.
  • (Me) I'm going to make an issue about addressing this globally - also, can you change details to use 86_400
  1. Validate accelerometer processing separately for iOS and Android.
  • ENMO assumes comparable units and gravity scaling across platforms. Accelerometer units, sampling patterns, missingness, and ENMO distributions should be checked separately by OS.
  • (Me) Data rates, quality do differ substantially between iOS and Android. Some of these differences change based on OS version, sometimes they change based on app updates. It is chaotic, Android is currently frequently very low quality.
  1. Reconsider Frequency.HOURLY_AND_DAILY
  • The name suggests hourly and daily outputs, but the implementation produces recording-level and daily RAR summaries. recording, daily, or both may better describe the outputs.
  1. Review missing data handling for IV and the average-day profile.
  • For IV, missing epochs are excluded from consecutive differences, but normalization still uses all epoch positions. Using the number of valid consecutive pairs may be more appropriate. Also, _average_day_profile() mean-fills completely missing clock-time bins, which could bias L5, RA, and L5 timing. A minimum clock-time coverage criterion may be preferable.
  1. Explicitly test DST.
  • Local days can contain 23 or 25 hours rather than 24. The fixed SECONDS_PER_DAY = 86400 assumption could affect coverage, day alignment, L5/M10 timing, and acrophase.
  • (Me: This is a general problem with approaches throughout the codebase. We need to examine this, and replace the existing date-time functions etc. There is or will be an issue about this soon, but I agree this should be handled in anything new that we add.)
  1. Verify cosinor acrophase mapping to local clock time.
  • The reported phase depends on the time origin. Since cosinor_acrophase_h represents clock time, the mapping between array time zero and local time should be explicitly ensured, particularly for partial days and DST transitions.
  • (Jinjoo) Since this function produces statistical analysis outputs, I think these details are worth addressing before making it a default. Otherwise, users may run the function without being aware of these assumptions and potential limitations)
  • (Me: I can't comment on correctness here, but sane and well documented defaults are very important.)

@biblicabeebli

Copy link
Copy Markdown
Member

On AI tooling: the substance of this work is my own. The rest-activity rhythm methods (IS, IV, RA, cosinor) come from a library I wrote and validated against real NHANES data before this PR and that's my prior research, not anything generated here. The engineering calls were mine as well: what to fix, what to leave alone, how to structure the tests, and how to respond to review.

  • Do you have references to/about that work? (even if it wasn't published work, its useful to know where work came from originally and document it.) I see some references in rhythms.md.

I do use AI (Claude) in my workflow, mainly for drafting and thinking through options, but I direct it and verify everything it helps with for this PR that meant reproducing each issue myself, writing and running the tests, running the full ruff/mypy/pytest gauntlet locally, and confirming behaviour before pushing I don't submit anything I can't explain or haven't checked.
So the methods, the judgment, and the verification are mine, and I stand behind all of the code. I think transparency here is the right default, so I'm glad you're putting a policy together and happy to follow whatever the lab lands on.

  • Ok, understood, and I'll trust you. (I can be a bit prickly when I perceive the earnest-but-annoying LLM chatbot voice, and particularly as a dev, we are exposed to it constantly. This will not be the only code that has used ai assist.)

@biblicabeebli

Copy link
Copy Markdown
Member

Code style request
(shouldn't take too long)

  • Could you please go through the code and add some vertical whitespace.

  • There's no "correct" way to do this, but the best I've heard is "separate the thoughts".

    • but just do one new-line
  • Please add a comment wher there is code that is...

    • particularly compacted or terse
    • particularly obscure
    • of unclear purpose,
    • a function call name that doesn't explain itself very well [in this context]
    • seems dumb but is necessary
    • is present in order to handle "buggy data"

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Thanks and no rush understood.

On references: the methods come from actrhythm, a small library I wrote implementing these non-parametric rest-activity metrics (IS, IV, RA with L5/M10) and a single-component cosinor: github.com/ceyhunolcan/actrhythm. Method references are Van Someren (1999) and Gonçalves (2014) for the nonparametric metrics and Cornelissen for the cosinor the ones cited in rhythms.md. I developed and applied these in a preprint of mine, a cross-sectional NHANES 2013-2014 study of olfactory dysfunction and 24-hour activity-rhythm fragmentation (n=2,327), on Research Square: https://doi.org/10.21203/rs.3.rs-9830931/v1 (analysis code at github.com/ceyhunolcan/od-activity-rhythm, Zenodo 10.5281/zenodo.20132927). In actrhythm the implementations are pinned to analytically-derived values (IV of an alternating series = 4.0, IS of identical days = 1.0, RA on a known profile = 9/11), the same ground-truth style as the tests in this PR. Glad to add any further refs into rhythms.md.

On your colleague's review: thank you, these are careful and well-taken points. A couple (the IV missing-data normalization and coverage-dependence of the rhythm metrics) I'd rather handle properly than patch quickly, so I'll work through them, a minimum daily-coverage criterion before counting valid days, IV normalized over valid consecutive pairs, the average-day-profile fill that can bias L5/RA, and the acrophase-to-local-clock mapping, along with the
vertical whitespace / explanatory comments and the switch to 86_400 in the same pass. Agreed the DST point is codebase-wide; I'll handle it soundly in this new code and keep the assumptions explicit in the docs. No rush on my side either,I'd rather get these right.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Pushed the cosinor acrophase precondition note, the epoch_seconds/epochs_per_day document clarification, and the IV normalization correction (now dividing over valid consecutive pairs instead of the raw epoch count, with a gappy-data regression test). Since the two coverage-related concerns (#1 and #5) are essentially one question concerning the amount of coverage we need before reporting a metric, I would like to validate the policy with you before implementing them.

#5 (average-day profile): As your colleague pointed out, _average_day_profile currently uses the global profile mean to fill completely empty clock bins, which biases L5/RA because a missing nighttime bin receives a daytime-inclusive average and appears overly busy. Under-covered bins will remain as NaN after I remove that fill. How should windows that straddle missing bins be handled by L5/M10?

If we choose strict: L5/M10 return NaN when there is no complete window, and a 5h/10h window is only valid if all of its bins are observed. Metrics that are straightforward and conservative are only reported when they are fully supported and if we choose tolerant: if coverage exceeds a criterion (such as ≥2/3 or ≥80%), a window mean is calculated over its observed bins; otherwise, NaN.

My lean is strict, it's the cleaner story for a statistical default, and it composes with the valid-day gate below, so we only report metrics we can stand behind. The tradeoff is more NaNs on gappy records, which I'd argue is the honest outcome. Either way I'll make L5/M10 NaN-aware and document the rule.

#1 (valid-day counting): related, and I saw that the module already had the necessary machinery. The MIN_DAY_COVERAGE = 0.5 constant is already used by _daily_frame to gate daily rows every day. Although no single day is sufficiently covered, six half-observed days count as three valid days and pass min_valid_days=3 because the participant-level valid_days count in run() is (all non-NaN epochs) / epochs_per_day. If each one of them passes the coverage threshold, I'll adjust it to just count one day. The policy challenge there is whether to adopt a more stringent wear threshold or maintain the current 0.5, which unites both gates on a single constant. Although I might suggest using ≥16 h/day (~0.67) in previous actigraphy work, 0.5 is more in line with what is already included in the module.

If you don't have a preference, I'd be happy to use my leans (strict windows + uniform 0.5). I just wanted to confirm the thresholds with you first because these are methodological decisions that should be agreed upon before I lock them in.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Quick housekeeping note: GitHub is now flagging a pyproject.toml conflict. It's just the mypy overrides block, your shapely/type-check cleanup on the base (dropping holidays/ratelimit/shapely/timezonefinder and enabling those checks) overlaps the pandas-override line I'd removed earlier, so it's a textual overlap rather than a real disagreement; your version is the fuller cleanup and already covers it. Happy to rebase onto the current base and take your pyproject.toml, but since your review process rebases this branch anyway, I'll leave it for you to fold in unless you'd rather I push a rebase. (Just let me know and letting you know about it )

@biblicabeebli

Copy link
Copy Markdown
Member

You are welcome to rebase or merge at your preference and pace, this is 99% new code so excepting glitches like the .toml details it should be low on conflicts. (there's always I'll review a final file list before merging.) I keep a feat-oak-rest-activity-rhythms branch pointed at your state, I'll make sure it gets git reset --hard (or whatever) on your repo branch state if you do a rebase.

There are other changes coming in, I'll mention or make post-merge cleanups if something comes up.

@ceyhunolcan
ceyhunolcan force-pushed the feat-oak-rest-activity-rhythms branch from a6d9d96 to 222b0e1 Compare August 19, 2026 20:30
@biblicabeebli

Copy link
Copy Markdown
Member

(the target branch has been merged into develop, retargeting this pull to develop)

@biblicabeebli
biblicabeebli changed the base branch from ruff-check-reflow-and-typing to develop August 25, 2026 19:05
…view)

- IV divides successive-diff and deviation sums by valid-pair and valid-point
  counts, not raw epoch count, so missing epochs don't bias it (reduces to the
  Van Someren n/(n-1) form when complete); add gappy-data regression test
- clarify epoch_seconds vs epochs_per_day (86_400/epoch_seconds) in docs
- document cosinor acrophase midnight-alignment precondition; use 86_400
@ceyhunolcan
ceyhunolcan force-pushed the feat-oak-rest-activity-rhythms branch from 222b0e1 to cd6dce9 Compare August 25, 2026 23:02
@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Re-rebased onto develop now that the base merged in the retarget was clean, no conflicts (my changes are additive to oak plus the docs and blame-ignore entries, and pyproject already matches develop). Full oak suite (26), mypy, and ruff all pass on top of develop's current tip. Ready for your mirror to re-sync, and for the final file-list review whenever you get to it.

@biblicabeebli

Copy link
Copy Markdown
Member

Jinjoo

Thank you for answering my questions and for making these revisions.

I have two follow-ups from my colleague, @jinjoo

  1. Daily coverage threshold: For MIN_DAY_COVERAGE = 0.5, I wanted to ask whether there is a reference supporting this threshold. Prior studies using wearables require >=16 hours of wear time per day, often for >=3 valid days in a 7-day monitoring period. In that context, 0.5 seems relatively permissive for valid-day counting. (would appreciate understanding the reasoning or a pragmatic default that users can adjust.)

[Eli Note] I'd like to see some more sane defaults, and comments in the function-level documentation stating some sane defaults values. (In general)

  1. Existing open-source packages: I forgot to ask initially; I also wanted to ask about for implementing these rhythm metrics directly in Forest rather than existing open-source packages. E.g., CosinorPy is a published Python package that supports single- and multi-component cosinor modeling, diagnostics, and visualization:
    https://pypi.org/project/CosinorPy/
    https://link.springer.com/article/10.1186/s12859-020-03830-w

Similarly, pyActigraphy already implements non-parametric RAR metrics:
https://pypi.org/project/pyActigraphy/
https://doi.org/10.1371/journal.pcbi.1009514

Is there a specific reason to hard-code these methods within Forest instead of using or wrapping these existing packages?

[Eli note] The primary goal here should be readability. Those packages look legit, but they also look like they have complex function signatures. Where possible I prefer small well-named functions that implement the relevant.


[And the rest is me again]

There have been some surrounding code changes

  • Constants are more collected in the forest.constants file
  • So please use forest.constants.SECONDS_IN_DAY in place of SECONDS_PER_DAY
    • (it is very difficult to gauge whether code within forest will ever handle time issues like non-24 days)
  • I'm still assessing how to contain tree-level common components, particularly for Oak. For now keep your MIN_DAY_COVERAGE (or whatever you are replacing it with) in the file, I will address placement later.
  • Oak has been reorganized from a single file named "base.py" into a preprocess.py, analysis.py, and runners.py.
    • (This isn't necessarily the final naming, but it needs to happen as we merge your work in.)
    • Would appreciate if you could respond with your ideas about whether/how this applies to you.
  • Expand acronyms like rar in rar_metrics to the full words except where it just gets excessive. The character limit is no longer 80.

Typing issues

  • Add subtyping to the list returns (like list[str], etc.)
  • I'm not liking the way dicts are used to hide typing
    • Addressing this from with a refactor to smaller well typed functions would probably help.
    • (see jasmine/sogp_gps.py - not a fan of those variable names, but the type checker means I can forgive it.)
    • functions are l5_m10, cosinor, rar_metrics
    • rar_metrics seems to be a function that does 95% of the work that composes the contents of a row in a csv. You can sidestep the issue here by passing the list in and appending inside the function. (that dict is unavoidable)
    • cosinor is a function that does real math, it needs to return well typed values.

General

  • apply the pathjoin pattern to the other os.path functions
    • (that this was not done implies you directed an LLM to do the transform, please ensure you are involved in your changes.)
  • rename _parse_time_utc() to indicate it exists for the purpose of being an index, not a general function
  • Expand acronyms like rar in rar_metrics to the full words except where it just gets excessive. The character limit is no longer 80.
  • Rename your not-raw-math functions to be more expressive and telegraph what they do.
    • like "load_participant_activity" is a good name.
    • (Naming things correctly is the hardest problem in computer science, I'm picky.)
  • Every function starting with an underscore should not use that pattern. rename them.
    • def _func_name(...) should be reserved for programmers communicating to other programmers that code is special. You are using it to create private functions (bad) or indicate they are too simple to require full documentation (totally reasonable).

Documentation

  • In general your documentation is speaking one notch too textbooky and Technically Correct.
    • Fill it out a little, give readers full sentences and punctuation to make it flow. (Do this yourself, do not use an LLM for the bulk documentation.)
    • _(Based on your profile I am guessing you are a non-native English speaker. Please let me know if that is an unreasonable assumption, my goal is to meet you at your level, and [if required] be your native english tone checker. LLMs have made guessing this from text alone much harder.)
  • Assume the reader is less of a domain expert than you, less familiar with the acronyms, and a little bit dumb.
    • Like ENMO. It's weird. I would need it spelled out.
    • Its ok to repeat some things in documentation, especially instead of directing them to a different document.
  • Name the executive summary something other than executive summary. (llm?)
  • Get rid of installation instructions. (llm?)
  • This code produces special output, so it needs examples of output and a guide of how to read it.
  • The documentation should extend to some hints for how to read the output from a domain expert.
    • Output documentation in particular is read by more people and by more non-experts.
    • Like "24 hours of constant activity would be strange and indicates weird data" would be the minimum.
    • Referencing helpful literature or sources on what some of the numbers mean "in the real world" is much better.

Naming Changes

  • I would like rhythms.py changed to circadian_rhythms.py
    • I think rhythms is too generic.
  • Change the word epoch. Everywhere. To ... something else. Anything else.
    • it is a specialized word that means different things in different domains
    • it is not used by native english speakers
    • I do not think it descriptively communicates what you are trying to communicate.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Thanks both, these are useful comments.

Daily coverage threshold: you're correct, and I don't have a reference for 0.5. It was already in the module as the gate for generating daily rows and I repurposed it, which was the wrong choice for a participant-level inclusion
criterion. I'll use the convention you mention instead: a min_valid_hours_per_day parameter defaulting to 16.0, converted internally to the required fraction, keeping the >=3 valid days requirement as it is. That is the criterion I used in my own NHANES analysis, so I can document the reasoning rather than just the number, and it stays adjustable for users with different wear protocols. I'll put the default, the rationale, and the common alternatives in the function docstring.

Existing packages: I did look at both, and my reasoning is close to Eli's point. Each non-parametric metric is a short, well-defined formula, so a small named function per metric is easier to read, to test against analytically known values, and to reason about than wrapping a package with a much larger API. It also avoids adding a dependency for what amounts to a few dozen lines of arithmetic. CosinorPy is a good package and does considerably more than this module needs (multi-component fits, diagnostics, plotting), and pyActigraphy brings its own data model and readers for device formats that Forest does not use. If the lab later wants multi-component cosinor or the wider pyActigraphy feature set, wrapping one of them would be the sensible route, and I will note that in the documentation.

Oak reorganization: my module splits along the same lines as the split in the tree. Preprocessing includes the ENMO calculation, the timestamp index, and the day-grid alignment; analysis includes IS, IV, RA with L5/M10, the average-day profile, and the cosinor; the runner includes the participant loop, frequency handling, and CSV writing. So the separation applies to me directly.

My instinct is to keep it as a self-contained module that follows the same internal separation rhythm metrics are a parallel analysis to step counting rather than another layer of it, they share no preprocessing (ENMO per interval is a different operation from the 10 Hz resampling in preprocess_bout), and keeping them together makes the module readable on its own. You are deciding how tree-level components are contained, though, so tell me which you prefer. If you do want the fold-in, I would rather do it as a follow-up than in this branch, so the file list you review stays a single new module instead of three modified ones.

Naming and constants: moving to forest.constants. SECONDS_IN_DAY, renaming rhythms.py to circadian_rhythms.py, expanding rar to the full words, removing the leading underscores, and renaming _parse_time_utc to state that it constructs the index, while keeping the coverage constant in the file for now. I'm substituting "interval" for "epoch" throughout, so interval_seconds and intervals_per_day. One thing to flag: that rename also changes the n_valid_epochs output column, which is user-facing, so say if you would rather the column names stay as they are. Also happy to add a file header in the same format as the other oak modules if you want authorship recorded that way.

Typing: in line with the pattern in bonsai and jasmine, cosinor will return a dataclass with typed fields instead of a dict. Since the row dict is the one that has to remain, rar_metrics will take the list and append its row inside. I'll add element types to the list annotations. On the os.path discrepancy: I used pathjoin for the joins but left two isdir calls bare. I appreciate you pointing that out, I should have caught it. fixing both.

I'll do the rewriting myself. Removing the installation section and the "executive summary" heading, spelling out ENMO and the rest on first use, writing in longer sentences, and adding worked output examples along with guidance on how to interpret the numbers, including what unusual values indicate about the data and what the literature links them to.

And you're right, I don't speak English as my first language, so that's a sensible guess rather than an unreasonable one. The tone check would be very appreciated. When something is off, just let me know and I'll take care of it.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

Also related to the column-name question the output files are also rar_summary.csv and <backend_id>_rar_daily.csv, so the same question applies there since "rar" is one of the acronyms you asked me to expand. I've left both the columns and the filenames alone pending your preference.

@biblicabeebli

Copy link
Copy Markdown
Member

@ceyhunolcan please take a look at my recent comments on the #279 issue about the requirements for LLM contributions.

@ceyhunolcan

Copy link
Copy Markdown
Contributor Author

@ceyhunolcan please take a look at my recent comments on the #279 issue about the requirements for LLM contributions.

I just read the guidelines after seeing your note on #279.  I'm finishing up the remaining points. When I push I'll include the AI usage statement in addition to the output documentation.

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.

2 participants