fossasia / pslab-python

Python Library for PSLab Desktop: https://pslab.io
GNU General Public License v3.0
1.62k stars 226 forks source link

Create a CLI application #146

Closed bessman closed 3 years ago

bessman commented 3 years ago

Some users might not need the full GUI suite offered by pslab-desktop, but might still want a nicer UX than just typing into the Python REPL. We should create a CLI application that can handle certain common tasks, like collecting samples with the oscilloscope, outputting a waveform, etc.

The CLI should be able to:

  1. Collect data from the oscilloscope and logic analyzer.
  2. Plot collected data (probably using matplotlib).
  3. Save collected data to a suitable format (probably CSV initially; reevaluate later).
  4. Load custom waveform signals, either as user-provided functions or from a provided input file.
  5. Output signals on the waveform generator.
  6. Set current and voltages on the power supply.
  7. Reading from sensors would be nice, but not required immediately.

This task is dependent on the ongoing effort to refactor the Sciencelab class into smaller modules (#127). Be advised that the API for some of the above mentioned instruments are subject to change as that task progresses. So far, the oscilloscope and logic analyzer are mostly complete and should be stable.

nkpro2000sr commented 3 years ago

can i work on this?

bessman commented 3 years ago

Please do! 😃

bessman commented 3 years ago

@nkpro2000sr Please also take a look at our new contributor guidelines.

nikhiltidke101 commented 3 years ago

I would like to work on this. Can I?

bessman commented 3 years ago

Hi @nikhiltidke101. nkpro2000sr has already been assigned this task, and it is not really suitable for multiple people to work on it simultaneously.

We are currently a little short on beginner-friendly tasks, but if you would like to help out I would recommend just starting to use the PSLab and help fix any bugs you encounter. Something is bound to crop up 😃

orangecms commented 3 years ago

I have some examples here for usage, might help a bit: https://github.com/orangecms/pslab-python/tree/examples/examples

The one for the ToF (Time if Flight) proximity sensor needs a little update now that we have the new I2C API, though.

Another possible reference is https://github.com/fossasia/pslab-desktop/blob/master/scripts/bridge.py

nkpro2000sr commented 3 years ago

i have a doubt that, is collecting data from the oscilloscope and logic analyzer has to be collected until timeout or certain interrupt like pressing q?

orangecms commented 3 years ago

There are many possibilities like offering an argument to specify a time period. I could imagine subcommands like many modern CLIs offer them, e.g., pslab collect --instrument oscilloscope --duration 3s --output my-data.json. What do you think? :)

nkpro2000sr commented 3 years ago

nice :+1:. For plotting which will be nicer? while collecting (in live) OR after collected

orangecms commented 3 years ago

You can always plot in various ways afterwards. Keep data separate and reusable. :) The CLI also allows for scripting on a higher level, in a Unix way, so you can combine with other tools through pipes, for example.

We have the desktop app for live plotting already, so there is no need to duplicate that.

nkpro2000sr commented 3 years ago

suggestions please?

$ python PSL --help
usage: PSL [-h] [-p PORT] {collect} ...

optional arguments:
  -h, --help            show this help message and exit
  -p PORT, --port PORT  The name of the port to which the PSLab is connected

Functions:
  Functions to perform on PSLab

  {collect}

$ python PSL collect --help
usage: PSL collect [-h] -i INSTRUMENT [-c CHANNELS] [-d DURATION] [-o FILE_PATH] [-s]

optional arguments:
  -h, --help            show this help message and exit
  -i INSTRUMENT, --instrument INSTRUMENT
                        The name of the instrument to use
  -c CHANNELS, --channels CHANNELS
                        Number of channels to capture
  -d DURATION, --duration DURATION
                        Duration for capturing (in seconds)
  -o FILE_PATH, --output FILE_PATH
                        File name to store data as csv file
  -s, --stdout          Enable it to output data as json in stdout

$ python PSL -p /dev/USB0 collect --instrument oscilloscope --duration 3 --output my-data.csv 

$ python PSL -p /dev/USB0 collect --instrument logic_analyzer --channel 2 --stdout > my-data.json
bessman commented 3 years ago

Very nice! The only thing I would add to the help text is a list of available instruments.

orangecms commented 3 years ago

Really cool! For intuitive use, I would suggest to always print to stdout unless a -o option for an output file is given, and default to linewise CSV unless a -j / --json switch is provided. The allows for any combination thereof then.

orangecms commented 3 years ago

Another little thing: Commands are usually all lowercase. There is already a psl command https://docs.bmc.com/docs/PATROLAgent/110/psl-psl-compiler-command-723218465.html#:~:text=The%20psl%20command%20creates%20an,can%20be%20used%20in%20the%20. so I would suggest to go with the full name pslab. I will make sure that the name for the desktop app will be pslab-desktop, which makes it similar to signal-desktop and other similar apps.

nkpro2000sr commented 3 years ago

But, I have planned to create PSL/__main__.py. so, it will be like python -m PSL .... Also it didn't required any extra setup, just pip install pslab would be enough.

bessman commented 3 years ago

You can add the CLI application as either a scripts or console_scripts entry in setup.py. That way, it can be run directly from the command line as pslab, without python -m ....

https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html

nkpro2000sr commented 3 years ago

thanks, i didn't aware of that.

nkpro2000sr commented 3 years ago

suggestions please?

[nkpro@h0me pslab-python]$ pslab -h
usage: check.py [-h] [-p PORT] {collect,wave} ...

optional arguments:
  -h, --help            show this help message and exit
  -p PORT, --port PORT  The name of the port to which the PSLab is connected

Functions:
  Functions to perform on PSLab.

  {collect,wave}
[nkpro@h0me pslab-python]$ pslab wave -h   
usage: check.py wave [-h] {gen,load} ...

optional arguments:
  -h, --help  show this help message and exit

Wave Functions:
  {gen,load}
[nkpro@h0me pslab-python]$ pslab wave gen -h
usage: check.py wave gen [-h] -f FREQUENCY [FREQUENCY ...] [-p PHASE] {SI1,SI2} [{SI1,SI2} ...]

positional arguments:
  {SI1,SI2}             Pin(s) on which to generate a waveform

optional arguments:
  -h, --help            show this help message and exit
  -f FREQUENCY [FREQUENCY ...], --frequency FREQUENCY [FREQUENCY ...]
                        Frequency in Hz
  -p PHASE, --phase PHASE
                        Phase between waveforms in degrees
[nkpro@h0me pslab-python]$ pslab wave load -h
usage: check.py wave load [-h] (--table TABLE | --table-file [TABLE_FILE]) {SI1,SI2}

positional arguments:
  {SI1,SI2}             Pin(s) on which to load a table

optional arguments:
  -h, --help            show this help message and exit
  --table TABLE         Table to load in pin SI1 as json
  --table-file [TABLE_FILE]
                        Table to load in pin SI1 as json file. Default is stdin
[nkpro@h0me pslab-python]$ pslab wave gen SI1 SI2 -f 50 60 -p 10
[nkpro@h0me pslab-python]$ pslab wave load SI1 --table [0,1.65,3.3,1.65,0,-1.65,-3.3,-1.65,0]
[nkpro@h0me pslab-python]$ cat table.json | pslab wave load SI1 --table-file
[nkpro@h0me pslab-python]$ pslab wave load SI1 --table-file table.json
orangecms commented 3 years ago

Is there a branch we can check out to play around with it? So far it looks quite nice to me :)

bessman commented 3 years ago

PRs can be checked out directly:

git fetch upstream pull/147/head:cli
git checkout cli

@nkpro2000sr The syntax looks good! I'll try it out and come back with more feedback.

orangecms commented 3 years ago

Yea sorry, I missed the draft PR, thank you!

Skynet843 commented 3 years ago

is Issue still open can i work on that?

nkpro2000sr commented 3 years ago

@nkpro2000sr The syntax looks good! I'll try it out and come back with more feedback.

Any feedback ... :eyes:

bessman commented 3 years ago

Yeah, sorry, been kind of swamped this week. Feedback coming up.

bessman commented 3 years ago

All right, first and foremost, thanks for your patience!

I'll go through the commands in order:

nkpro2000sr commented 3 years ago

@bessman fixed :+1:

bessman commented 3 years ago

Thank you. pwm map works well now, and the format example in wave load is good. collect oscilloscope is still problematic though; it runs for much longer than the set duration. With --duration 1 it runs for almost a minute.

nkpro2000sr commented 3 years ago

It collects 2e6 samples for a second (-d 1). I doubt that delay is due to massive samples fetched.

could you please check scope.capture(1, 2e6, 0.5) ?

bessman commented 3 years ago

The oscilloscope can't capture more than 1e4 samples at a time, so scope.capture(1, 2e6, 0.5) will just complain about that. There is a fair bit of overhead, time wise, between individual capture calls, so capturing 2e6 samples will take a lot longer than just 2e6 0.5 1e-6.

for i in range(200):
    scope.capture(1, 10000, 0.5)

takes a similar amount of time.

nkpro2000sr commented 3 years ago

would this solves?

+        st = time.time()
         xy = np.append(xy, scope.capture(channels, samples, min_timegap), axis=1)
-        duration -= max_duration
+        duration -= time.time() - st
bessman commented 3 years ago

Yes, that should work. I'll test it tomorrow. Do you not have a device to test with?

Missing samples is unavoidable; after each capture, the 10000 samples (20 kB) must be transferred across the 1 Mbaud serial connection, which takes 160 ms. During that time, no samples can be collected.

nkpro2000sr commented 3 years ago

Yes, that should work. I'll test it tomorrow.

:+1:

Do you not have a device to test with?

No, i don't have :(

Missing samples is unavoidable; after each capture, the 10000 samples (20 kB) must be transferred across the 1 Mbaud serial connection, which takes 160 ms. During that time, no samples can be collected.

ok :+1:

bessman commented 3 years ago

It works now, well done! I'm impressed you managed to do so much without have the hardware to test against.

Do you think you could also write some tests for the cli module?

nkpro2000sr commented 3 years ago

@bessman Added tests for CLI. please check.

bessman commented 3 years ago

Thanks!

Could you also write tests for the logic_analyzer and oscilloscope functions? The other missed lines are OK because they just use already tested interfaces, but those functions contain logic that should ideally be covered.

And one more thing: We are moving from unittest to pytest, so please use pytest-mock instead of unittest.mock. It should be a drop-in replancement.

nkpro2000sr commented 3 years ago

@bessman Added testes for logic_analyzer and oscilloscope.

Could you add json traffic recordings for these. Since i don't have device i am not able to generate those json fils.

bessman commented 3 years ago

Thank you @nkpro2000sr, your work has been merged!