BCDA-APS / use_bluesky

Tools to help APS use the Bluesky Framework (https://blueskyproject.io/)
8 stars 3 forks source link

Windows installation instructions must be updated #114

Open prjemian opened 2 years ago

prjemian commented 2 years ago

They are out of date.

prjemian commented 2 years ago

MongoDB

See this for the mongodb: https://github.com/BCDA-APS/use_bluesky/blob/main/install/windows.md#install-mongodb Don't be scared, it is super easy.

prjemian commented 2 years ago

Anaconda

MongoDB is separate from Anaconda. For Anaconda, download and install from here: https://www.anaconda.com/products/individual This page looks at the host OS you are using with your browser and offers installer for that OS by default.

prjemian commented 2 years ago

Conda environment for Bluesky

latest Bluesky environment (for Windows), download from here: https://raw.githubusercontent.com/BCDA-APS/use_bluesky/main/install/win_2022_1.yml

Line 4 has the Windows command to install but this might be a challenge for you to get to the correct directory with conda activated. https://github.com/BCDA-APS/use_bluesky/blob/83e80ac9f3fd41b46c061a5dd79262e35c176daa/install/win_2022_1.yml#L4

I recommend a command shell for this: Start menu, Anaconda folder, Anaconda Prompt (or Powershell, your choice).

jilavsky commented 2 years ago

Notes: MongoDB installation asks some configuration questions. Not sure what is right to do. Our MongoDB page: https://github.com/BCDA-APS/use_bluesky/blob/main/install/windows.md#install-mongodb has obsolete info about downloading BlueSky. It needs to be removed or updated - it is replaced by the yml file configuration below.

To install yml file: Start Conda power shell change to folder where the yml file is (for me cd .\Downloads\ ) Execute conda env create --force -f win_2022_1.yml took may be 5 minutes to finish, but seems OK.

prjemian commented 2 years ago

@jilavsky asks:

Any test how to verify that all is working?

Open a new Jupyter notebook and check that the bluesky_2022_1 kernel is available. Use the ophyd simulators to see that things are working:

from apstools.utils import listobjects
listobjects()

This will be an empty table (nothing loaded yet). Next, load the simulators.

from ophyd.sim import *
listobjects()

This get some results:

In [4]: listobjects()
=================== ===================== ======== =========
name                ophyd structure       EPICS PV label(s) 
=================== ===================== ======== =========
ab_det              ABDetector                     detectors
bool_sig            Signal                         detectors
det                 SynGauss                       detectors
det1                SynGauss                       detectors
det2                SynGauss                       detectors
det3                SynGauss                       detectors
det4                Syn2DGauss                     detectors
det5                Syn2DGauss                     detectors
det_with_conf       DetWithConf                    detectors
det_with_count_time DetWithCountTime               detectors
direct_img          DirectImage                    detectors
direct_img_list     DirectImage                    detectors
identical_det       SynGauss                       detectors
img                 SynSignalWithRegistry          detectors
invariant1          InvariantSignal                detectors
invariant2          InvariantSignal                detectors
jittery_motor1      SynAxis                        motors   
jittery_motor2      SynAxis                        motors   
motor               SynAxis                        motors   
motor1              SynAxis                        motors   
motor2              SynAxis                        motors   
motor3              SynAxis                        motors   
motor_empty_hints1  SynAxisEmptyHints              motors   
motor_empty_hints2  SynAxisEmptyHints              motors   
motor_no_hints1     SynAxisNoHints                 motors   
motor_no_hints2     SynAxisNoHints                 motors   
motor_no_pos        SynAxisNoPosition              motors   
noisy_det           SynGauss                       detectors
pseudo1x3           SPseudo1x3                              
pseudo3x3           SPseudo3x3                              
rand                SynPeriodicSignal              detectors
rand2               SynPeriodicSignal              detectors
sig                 Signal                                  
signal              SynSignal                               
=================== ===================== ======== =========

Out[4]: <pyRestTable.rest_table.Table at 0x7f9ac726a490>

Then, let's try to move the motor (using ophyd) to +3 from its current position (argh! this one does not have a .move() method):

In [7]:     print(f"{motor.position}")
   ...:     motor.setpoint.put(motor.position+3)
   ...:     print(f"{motor.position}")
0
3.0

Now, let's try some activities with the bluesky RunEngine (and no databroker/MongoDB):

from bluesky import RunEngine
from bluesky import plans as bp
from bluesky import plan_stubs as bps
from bluesky.callbacks.best_effort import BestEffortCallback

RE = RunEngine({})
RE.subscribe(BestEffortCallback())

def my_plan():
    "Move motor -3 from current position"
    print(f"{motor.name}: {motor.position = }")
    yield from bps.mvr(motor, -3)
    print(f"{motor.name}: {motor.position = }")

RE(my_plan())

# Now, a scan of noisy_det v motor

RE(bp.scan([noisy_det], motor, -1, 1, 11))

Here's what I just got:

motor: motor.position = 3.0
motor: motor.position = 0.0

Transient Scan ID: 1     Time: 2021-11-12 13:04:05
Persistent Unique Scan ID: '814bf988-b637-439e-8770-b7485d2def2b'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |      motor |  noisy_det |
+-----------+------------+------------+------------+
|         1 | 13:04:05.0 |     -1.000 |      0.592 |
|         2 | 13:04:05.1 |     -0.800 |      0.664 |
|         3 | 13:04:06.2 |     -0.600 |      0.869 |
|         4 | 13:04:06.2 |     -0.400 |      0.863 |
|         5 | 13:04:06.2 |     -0.200 |      0.995 |
|         6 | 13:04:06.2 |      0.000 |      1.038 |
|         7 | 13:04:06.2 |      0.200 |      1.029 |
|         8 | 13:04:06.2 |      0.400 |      0.881 |
|         9 | 13:04:06.2 |      0.600 |      0.827 |
|        10 | 13:04:06.2 |      0.800 |      0.704 |
|        11 | 13:04:06.2 |      1.000 |      0.565 |
+-----------+------------+------------+------------+
generator scan ['814bf988'] (scan num: 1)

Out[11]: ('814bf988-b637-439e-8770-b7485d2def2b',)
prjemian commented 2 years ago

Next, you want to pick some EPICS PVs that you can read (and possibly write).

from bluesky.magics import BlueskyMagics
from ophyd import EpicsSignal, EpicsMotor

# this will get you %mov, %movr, etc.
get_ipython().register_magics(BlueskyMagics)

m1 = EpicsMotor("gp:m1", name="m1")
m1_DESC= EpicsSignal("gp:m1.DESC", name="m1_DESC")
calc = EpicsSignal("gp:userCalc5.CALC", name="calc")

m1.wait_for_connection()
m1_DESC.wait_for_connection()
calc.wait_for_connection()

# change the calc, then reset it
old_calc = calc.get()
print(f"{calc.get() = }")
%mov calc "D"
print(f"{calc.get() = }")
%mov calc old_calc 
print(f"{calc.get() = }")

This output (with my gp: IOC):

calc.get() = '0'
calc.get() = 'D'
calc.get() = '0'
prjemian commented 2 years ago
old = m1_DESC.get()
print(f"{old = }")

# Can't use %mov if the new value has  _any_  whitespace.  :(
%mov m1_DESC "elbow"
print(f"{m1_DESC.get() = }")

%mov m1_DESC old
print(f"{m1_DESC.get() = }")

in ipython

In [3]: old = m1_DESC.get()
   ...: print(f"{old = }")
   ...: 
   ...: # Can't use %mov if the new value has  _any_  whitespace.  :(
   ...: %mov m1_DESC "elbow"
   ...: print(f"{m1_DESC.get() = }")
   ...: 
   ...: %mov m1_DESC old
   ...: print(f"{m1_DESC.get() = }")
old = 'motor 1'
m1_DESC.get() = 'elbow'
m1_DESC.get() = 'motor 1'
prjemian commented 2 years ago

Jan suggests that we don't use the magics syntax in examples. Use of multiple alternate syntax makes this even more difficult to learn.