	subroutine dat_nexus
c	--------------------

	external dat_nexus_desc
	external dat_nexus_opts
	external dat_get_datanumber ! get number on first line
	external dat_nexus_read

	integer dtype/0/

	call dat_init_desc(dtype, dat_nexus_desc)
	call dat_init_opts(dtype, dat_nexus_opts)
	call dat_init_high(dtype, dat_get_datanumber)
	call dat_init_read(dtype, dat_nexus_read)
	end


	subroutine dat_nexus_desc(text)
!	-------------------------------
	character*(*) text  ! (out) description

!             type    description
!             ----------------------------------
	text='NEXUS   NeXus data format'
	end


	subroutine dat_nexus_opts
!	-------------------------
	implicit none
	character spec*16

	call sys_getenv('dat_defspec', spec)
	call str_upcase(spec, spec)
	if (spec .ne. ' ') then
	  print '(x,2a/)','valid only for instrument ',spec
	endif
	if (spec(1:5) .eq. 'FOCUS') then
	  print '(x,a)'
	1  ,'from,to:  detector range (default: averaged over all)'
	1  ,'bank:     detector bank, u,b,l,m (default: m=merged)'
	1  ,'axis:     time or theta'
	else if (spec(1:4) .eq. 'RITA') then
	  print '(x,a)'
	1  ,'from:     window number (default: middle window)'
	1  ,'from,to:  window range'
	1  ,'axis:     x-axis to be choosen'
	1  ,'y:        y-axis to be choosen (aux, mon)'
	else if (spec(1:5) .eq. 'CAMEA') then
	  print '(x,a)'
	1  ,'axis:     x-axis to be choosen'
	1  ,'y:        y-axis to be choosen (0 (summed_counts), 1, 8 (segment number), tot (total_counts), mon, aux)'
	else if (spec(1:5) .eq. 'TRICS') then
	  print '(x,a)'
	1  ,'from,to:  detector range'
	1  ,'axis:     x-axis to be choosen'
	1  ,'frame:    frame number (default: all frames)'
	1  ,'det:      detector number (default: 2)'
	else if (spec(1:3) .eq. 'DMC') then
	  print '(x,a)'
	1  ,'cal:      calibration file'
	1  ,'filter:   threshold for spike filter (default: 4)'
	else if (spec(1:4) .eq. 'HRPT') then
	  print '(x,a)'
	1  ,'from,to:  time channel range (default: averaged over all)'
	1  ,'cal:      calibration file'
	1  ,'filter:   threshold for spike filter (default: 4)'
	else if (spec(1:5) .eq. 'MARS') then
	  print '(x,a)'
	1  ,'bank:     detector bank, e,i,m1,m2'
	1  ,'                         (elastic, inelastic, mon1, mon2)'
	1  ,'from,to:  detector range (default: averaged over all)'
	else if (spec .eq. ' ') then
	  print '(x,a)'
	1  ,'from:     first or only dataset (default: 1, RITA: middle window)'
	1  ,'to:       last dataset (default: max. or single)'
	1  ,'bank:     on FOCUS: detector bank, u,b,l,m (default: m=merged)'
	1  ,'axis:     x-axis to be choosen'
	1  ,'frame:    on TRICS: frame number (default 0)'
	1  ,'det:      on TRICS: detector number (default: 1)'
	1  ,'cal:      calibration file'
	endif
	print '(x,a)'
	1  ,'mon:      monitor for normalisation (auto, smon, pmon, bmon, time)'
	end


	subroutine dat_nexus_read
	1 (lun, forced, nread, pv, nmax, xx, yy, ss, ww)
!	------------------------------------------------
	implicit none

	integer lun	! (in) logical unit number (file will be closed if successful)
	integer forced	! 0: read only if type is sure; 1: forced read
	integer nread	! (out) >=0: = number of points read, file closed
	                !       -1: not correct type, file rewinded
	                !       -2: correct type, but unreadable, file rewinded
	external pv     ! (in) subroutine to put name/value pairs.
	                ! for numeric data:     call putval('name', value)   ! value must be real
			! for character data:   call putval('name=text', 0.0)
	integer nmax    ! max. number of points
	real xx(*)	! x-values
	real yy(*)	! y-values
	real ss(*)	! sigma
	real ww(*)	! weights  (original monitor)

! local
	include 'dat_nexus.inc'

	integer i,j
	character magic*4, filename*256
	integer li, lc, lm
	character cnt*64, mono*64, ins*64, axis2*64, signal*64
	character yaxis*64
	integer nsum, ngrp, nblk, xlen, nset
	real totcnts, sta, stp, weight
	integer from, to, lb, idet, icomp, iframe
	character bank*64, buf*16
	character monarray*64
	integer p_weight(2), p_monarray(2)
	integer istart
	integer n_monarray

	integer dat_comp
	external dat_comp, dat_nexus_putval


	if (forced .le. 0) then ! check for HDF-file
	  magic=' '
	  read(lun,'(a4)',err=9,end=9) magic
9	  if (magic .ne. char(14)//char(3)//char(19)//char(1) .and.
	1        magic(2:4) .ne. 'HDF') then
	    rewind lun
	    nread=-1
	    return
	  endif
	endif

c assume that we can open the HDF file, even when it is opened already by Fortran

	inquire(lun, name=filename)
	call NXswitchReport(0)
	status=NXopen(filename, NXacc_read, fileid)

	if (status .ne. NX_ok) then
	  rewind lun
	  call NXswitchReport(1)
	  nread=-1
	  return
	endif
	lp=1
	path='/'

	call dat_nexus_get('/instrument')
	if (type .ne. NX_char .or. status .ne. NX_OK) then
	  if (index(filename,'rita') .ne. 0) then
	    cdata = 'RITA2'
	  elseif (index(filename,'camea') .ne. 0) then
	    cdata = 'CAMEA'
	  else
	    goto 999 ! no instrument attribute
	  endif
	endif
	
	i=index(cdata, ' ')
	j=index(cdata, ',')
	if (j .eq. 0) j=len(cdata)
	i=min(i,j)-1
	if (i .lt. 1) goto 999 ! bad instrument attribute

	call dat_group(2, pv) ! importance level 2
	call pv('instrument='//cdata(1:i), 0.0)

	call str_upcase(instr, cdata(1:1)) ! take the first letter as code for the instrument

	call dat_start_options
	from=0
	to=0
	bank=' '
	xaxis=' '
	yaxis=' '
	iframe=-1
	idet=2
	if (instr .eq. 'F') then
	  call dat_int_option('from', from)
	  call dat_int_option('to',   to)
	  call dat_str_option('bank', bank)
	  call dat_str_option('axis', xaxis)
	elseif (instr .eq. 'R') then
	  call dat_int_option('from', from)
	  call dat_int_option('to',   to)
	  call dat_str_option('axis', xaxis)
	  call str_lowcase(xaxis, xaxis)
	  call dat_str_option('y', yaxis)
	  call str_lowcase(yaxis, yaxis)
	elseif (instr .eq. 'C') then
	  call dat_str_option('axis', xaxis)
	  call str_lowcase(xaxis, xaxis)
	  call dat_str_option('y', yaxis)
	  call str_lowcase(yaxis, yaxis)
	elseif (instr .eq. 'T') then
	  call dat_int_option('from', from)
	  call dat_int_option('to',   to)
	  call dat_int_option('det', idet)
	  call dat_str_option('axis', xaxis)
	  call dat_int_option('frame', iframe)
	elseif (instr .eq. 'H') then
	  call dat_int_option('from', from)
	  call dat_int_option('to',   to)
	elseif (instr .eq. 'M') then
	  call dat_str_option('bank', bank)
	  call dat_int_option('from', from)
	  call dat_int_option('to',   to)
	endif
	ymon=0
	monitor='auto'
	call dat_str_option('mon', monitor)
	icomp=0
	call dat_int_option('bin', icomp)
	nframes=0
	axis2=' '
	n_monarray=0
	if (yaxis .eq. ' ') yaxis='counts'

	if (instr .eq. 'D') then ! dmc
	  call str_trim(ins, '/nxentry/dmc/', li)
!	  this will also match NXpsd!
	  call str_trim(cnt, ins(1:li)//'nxdetector/', lc)
	  xaxis='two_theta'
	  axis1=cnt(1:lc)//'two_theta'
	  signal=cnt(1:lc)//'counts'
	else if (instr .eq. 'H') then ! hrpt
	  call str_trim(ins, '/nxentry/hrpt/', li)
!	  this will also match NXpsd!
	  call str_trim(cnt, ins(1:li)//'nxdetector/', lc)
	  xaxis='two_theta'
	  axis1=cnt(1:lc)//'two_theta'
	  signal=cnt(1:lc)//'counts'
	  axis2=cnt(1:lc)//'stroboscopic_time'
	  monarray='/nxentry/stroboscopic_monitor/data'
	  if (monitor .eq. 'auto' .or. monitor .eq. 'smon') then
	    n_monarray=-1
	  endif
	elseif (instr .eq. 'F') then ! focus
	  call str_trim(ins, '/nxentry/focus/', li)
	  call str_trim(cnt, ins(1:li)//'counter/', lc)
	  if (xaxis .eq. ' ') xaxis='time'
	  call str_lowcase(bank, bank)
	  if (bank(1:1) .eq. 't') then
	    call str_trim(bank, ins(1:li)//'tof_monitor/', lb)
	    axis1=ins(1:li)//'merged/time_binning'
	    signal=ins(1:li)//'tof_monitor'
	  else
	    if (bank(1:1) .eq. 'u') then
	      call str_trim(bank,'upperbank',lb)
	    elseif (bank(1:1) .eq. 'l') then
	      call str_trim(bank,'lowerbank',lb)
	    elseif (bank(1:1) .eq. 'b') then
	      call str_trim(bank,'bank1',lb)
	    else
	      call str_trim(bank,'merged',lb)
	    endif
	    call str_trim(bank, ins(1:li)//bank(1:lb)//'/', lb)
	    if (xaxis .eq. 'time') then
	      axis1=bank(1:lb)//'time_binning'
	      axis2=bank(1:lb)//'theta'
	    else
	      axis2=bank(1:lb)//'time_binning'
	      axis1=bank(1:lb)//'theta'
	    endif
	    signal=bank(1:lb)//'counts'
	  endif
	elseif (instr .eq. 'T') then ! trics
	  call str_trim(ins, '/frame0000/trics/', li)
	  if (iframe .ge. 0) write(ins(1:10), '(a,i4.4)') '/frame',iframe
	  call str_trim(cnt, ins(1:li)//'count_control/', lc)
	  if (xaxis .eq. ' ') xaxis='x'
	  if (idet .le. 0) idet=1
	  if (idet .gt. 3) idet=3
	  call str_trim(bank, ins(1:li)//'detector'//char(48+idet)//'/'
	1               , lb)
	  if (xaxis .eq. 'x') then
	    axis1=bank(1:lb)//'x'
	    axis2=bank(1:lb)//'y'
	  else
	    axis1=bank(1:lb)//'y'
	    axis2=bank(1:lb)//'x'
	  endif
	  signal=bank(1:lb)//'counts'
	  nframes=1
	elseif (instr .eq. 'C') then ! camea
	  call str_trim(ins, '/nxentry/CAMEA/', li)
	  call str_trim(cnt, ins(1:li)//'detector/', lc)
	  axis1=' '
	  if (yaxis .eq. 'aux') then
	    signal='/nxentry/aux_detector/data'
	  elseif (yaxis .eq. 'mon') then
	    signal='/nxentry/control/data'
	  elseif (yaxis .eq. 'tot') then
	    signal=cnt(1:lc)//'total_counts'
	  elseif (yaxis(2:) .eq. ' ' .and. yaxis(1:1) .ge. '0' .and. yaxis(1:1) .le. '9') then
            signal='/nxentry/CAMEA/segment_'//yaxis(1:1)//'/data'
	  else
	    signal='/nxentry/data/summed_counts'
	  endif
	  call dat_nexus_get('/nxentry/data/*')
	elseif (instr .eq. 'R') then ! rita
	  call str_trim(ins, '/nxentry/rita-2/', li)
	  call str_trim(cnt, ins(1:li)//'detector/', lc)
	  axis1=' '
	  if (yaxis .eq. 'aux') then
	    signal='/nxentry/aux_detector/data'
	  elseif (yaxis .eq. 'mon') then
	    signal='/nxentry/control/data'
	  else
	    axis2='w'
	    yaxis='counts'
	    signal=cnt(1:lc-1)//'windows/counts'
	  endif
	  if (from .gt. 0) then
	    if (to .lt. from) to=from
	  else if (from .eq. 0) then
	    from = 5
	    to = 5
	  endif
	  call dat_nexus_get('/nxentry/data/*')
	elseif (instr .eq. 'M') then
	  call str_lowcase(bank, bank)
	  if (bank(1:1) .eq. 'i') then
	    call str_trim(ins, '/inelastic/MARS/', li)
	    call str_trim(cnt, ins(1:li)//'inelastic_bank/', lc)
	    axis1=cnt(1:lc)//'time_binning'
	    axis2=cnt(1:lc)//'scattering_angle'
	  else
	    call str_trim(ins, '/elastic/MARS/', li)
	    if (bank .eq. 'm1') then
	      call str_trim(cnt, '/elastic/pre_sample_monitor/', lc)
	      axis1=cnt(1:lc)//'time_of_flight'
	    else if (bank .eq. 'm2') then
	      call str_trim(cnt, '/elastic/after_sample_monitor/', lc)
	      axis1=cnt(1:lc)//'time_of_flight'
	    else
	      call str_trim(cnt, ins(1:li)//'elastic_bank/', lc)
	      axis1=cnt(1:lc)//'time_binning'
	      axis2=cnt(1:lc)//'scattering_angle'
	    endif
	  endif
	  signal=cnt(1:lc)//'data'
	else ! any instrument
	  call str_trim(ins, '/nxentry/nxinstrument/', li)
	  call str_trim(cnt, ins(1:li)//'count_control/', lc)
	  axis1=' '
	  signal=cnt(1:lc)//'counts'
	endif
	call str_trim(mono, ins(1:li)//'monochromator/', lm)
	
	call dat_group(1, pv) ! importance level 1

	! the first column is a code (first letter of the instrument) saying that the item is present
	! a question mark is used for optional items

	call dat_nexus_r(pv,'DHFT M/owner')
	call dat_nexus_r(pv,'   T /nxentry/currentframenumber=frames')
	call dat_nexus_r(pv,'DHFTRCM/nxentry/title=Title')
	call dat_nexus_r(pv,'DHFTRCM/nxentry/start_time=Date')
	call dat_nexus_r(pv,'DHF   '//mono(1:lm)//'lambda')
	call dat_nexus_r(pv,'   T  '//mono(1:lm)//'wavelength')
	call dat_nexus_r(pv,'DH    /nxentry/sample/sample_name=sample')
	call dat_nexus_r(pv,'  FTRCM/nxentry/sample/name=sample')
	call dat_nexus_r(pv,'  FTRCM?/nxentry/sample/temperature=Temp')
	fvalue=0.0
	call dat_nexus_r(
	1  dat_nexus_putval,'DH    ?/nxentry/sample/temperature_mean=Temp')
	if (fvalue .ne. 0.0) then
	  call pv('Temp', fvalue)
	else
	  call dat_nexus_r(pv
	1               ,'DH TRC ?/nxentry/sample/sample_temperature=Temp')
	end if
	call dat_nexus_r(pv
	1               ,'DH  RC ?/nxentry/sample/temperature_stdDev=dTemp')
	call dat_nexus_r(pv,'DHFT  ?/nxentry/sample/magfield')
	call dat_nexus_r(pv,'    RC ?/nxentry/sample/magnetic_field')
	call dat_nexus_r(pv,'   T  /nxentry/sample/omega=om')
	call dat_nexus_r(pv,' H    ?/nxentry/sample/x_translation=stx')
	call dat_nexus_r(pv,' H    ?/nxentry/sample/y_translation=sty')
	call dat_nexus_r(pv,' H    ?/nxentry/sample/sample_stick_rotation=dom')
	call dat_nexus_r(pv,'DH    '//cnt(1:lc)//'two_theta_start=a4')

	call dat_group(2, pv) ! importance level 2

	call dat_nexus_r(pv,'D F   '//mono(1:lm)//'theta=a1')
	call dat_nexus_r(pv,'D FT  '//mono(1:lm)//'two_theta=a2')
	call dat_nexus_r(pv
	1             ,'DH   ?/nxentry/sample/sample_table_rotation=a3')
	call dat_nexus_r(pv,'DHFTRC ?/nxentry/sample/device_name')
	call dat_nexus_r(pv,'D     '//mono(1:lm)//'curvature=mcv')
	call dat_nexus_r(pv,'D     '//mono(1:lm)//'x_translation=mtx')
	call dat_nexus_r(pv,'D     '//mono(1:lm)//'y_translation=mty')
	call dat_nexus_r(pv,'D     '//mono(1:lm)//'phi=mgu')
	call dat_nexus_r(pv,'D     '//mono(1:lm)//'chi=mgl')
	call dat_nexus_r(pv,'DH    '//cnt(1:lc)//'countermode=Preset')
	call dat_nexus_r(pv,'  F   '//cnt(1:lc)//'count_mode=Preset')
	call dat_nexus_r(pv,'   T  '//cnt(1:lc)//'countmode=Preset')
	call dat_nexus_r(pv,'    RC /nxentry/control/mode=Preset')
	call dat_nexus_r(pv,'    RC /nxentry/control/preset=sMon')
	call dat_nexus_r(pv,'DHFT  ?'//cnt(1:lc)//'time')
	call dat_nexus_r(pv,'DHFT  '//cnt(1:lc)//'monitor=sMon')
	call dat_nexus_r(pv,'DHFT  '//cnt(1:lc)//'beam_monitor=bMon')
	call dat_nexus_r(pv,'D     '//cnt(1:lc)//'additional_monitor=aMon')
	call dat_nexus_r(pv,
	1  ' H    '//cnt(1:lc)//'radial_collimator_status=radcolstat')
	call dat_nexus_r(pv,
	1  ' H    '//cnt(1:lc)//'radial_collimator_type=radcol')
	call dat_nexus_r(pv,'DH    '//cnt(1:lc)//'proton_monitor=pMon')
	call dat_nexus_r(pv,'DH    /nxentry/sample/sample_mur=muR')
	call dat_nexus_r(pv,'   T  /nxentry/sample/chi')
	call dat_nexus_r(pv,'   T  /nxentry/sample/phi')
	call dat_nexus_r(pv,
	1  ' H    /nxentry/sample/sample_changer_position=chpos')
	call dat_nexus_r(pv,
	1  ' H    /nxentry/sample/sample_rotation_state=sarot')
	call dat_nexus_r(pv,'   T '//ins(1:li)//'detector2/two_theta=stt')
	call dat_nexus_r(pv,'   T ?'//ins(1:li)//'detector1/tilt=dg1')
	call dat_nexus_r(pv,'   T ?'//ins(1:li)//'detector2/tilt=dg2')
	call dat_nexus_r(pv,'   T ?'//ins(1:li)//'detector3/tilt=dg3')
	call dat_nexus_r(pv,'  F  /nxentry/end_time')
	call dat_nexus_r(pv
	1            ,' H    '//ins(1:li)//'Kollimator1/kollimator1=cex1')
	call dat_nexus_r(pv
	1            ,' H    '//ins(1:li)//'Kollimator1/kollimator2=cex2')
	call dat_nexus_r(pv
	1            ,' H    '//ins(1:li)//'exit_slit/width=d1w')
	call dat_nexus_r(pv
	1            ,' H    ?'//ins(1:li)//'beam_reduction/bottom=brbo')
	call dat_nexus_r(pv
	1            ,' H    ?'//ins(1:li)//'beam_reduction/left=brle')
	call dat_nexus_r(pv
	1            ,' H    ?'//ins(1:li)//'beam_reduction/right=brri')
	call dat_nexus_r(pv
	1            ,' H    ?'//ins(1:li)//'beam_reduction/top=brto')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'curvature_lower=mcvl')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'curvature_upper=mcvu')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'lift=mexz')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'omega_lower=moml')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'omega_upper=momu')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'vertical_tilt_upper=mgvu')
	call dat_nexus_r(pv,' H    '//mono(1:lm)//'paralell_tilt_upper=mgpu')

	call dat_group(3, pv) ! importance level 3
	call pv('Xaxis='//xaxis, 0.0)
	call pv('Yaxis='//yaxis, 0.0)

	if (axis1 .ne. ' ') then
	  call dat_nexus_get(axis1)
	  if (status .ne. NX_ok) then
	    print *,'axis ',axis1,' not found'
	    xlen=0
	  else
	    xlen=min(nmax,length)
	    if (icomp .gt. 1) then
	      stp=icomp
	      if (stp .lt. 1) stp = 1
	      xlen=dat_comp(0,0, p_array, xlen, 1, 1, 0.0
	1                   , stp, xlen/icomp,0)
	      call dat_copy2f(p_array, xx, xlen, 1)
	      do i=1,xlen
	        xx(i)=xx(i)/icomp
	      enddo
	    else
	      if (rank .eq. 2) then ! for rita: take 'from' window
	        if (sdate .gt. '2006-12-20') then ! new rita
	          if (from .ge. dim(1)) then
	            istart = 4
	          else
	            istart = (from - 1)
	          endif
	          xlen = dim(2)
	          call dat_extract(p_array, istart, dim(1), xx, xlen, 1)
	        else
	          if (from .ge. dim(2)) from = dim(2)
	          istart = dim(1) * (from - 1)
	          xlen = dim(1)
	          call dat_extract(p_array, istart, 1, xx, xlen, 1)
	        endif
	      else if (rank .eq. 1) then
	        call dat_copy2f(p_array, xx, xlen, 1)
	      else
	        xx(1)=0
	      endif
	    endif
	  endif
	else
	  xlen=0
	endif
	nread=0
	nset=0
70	if (n_monarray .ne. 0) then
	  call dat_nexus_get(monarray)
	  if (status .eq. NX_ok) then ! monitor array present
	    p_monarray(1)=p_array(1)
	    p_monarray(2)=p_array(2)
	    if (rank .eq. 1) then
	      n_monarray=dim(1)
	    else
	      print *,'illegal stroboscopic monitor dimension'
	      n_monarray=0
	    endif
	  endif
	endif        
	call dat_nexus_get(signal)
	if (status .ne. NX_ok) then
	  if (instr .eq. 'R') then
	    call dat_nexus_get('/nxentry/data/summed_counts')
	    axis2=' '
	  endif
	  if (status .ne. NX_ok) then
	    print *,'signal ',signal,' not found'
	    goto 999
	  endif
	endif
	if (rank .eq. 0) then
	  call dat_copy2p(p_array, fvalue)
	endif
	if (instr .eq. 'H') then
	  if (rank .ne. 2) then
	    axis2=' '
	    if (n_monarray .ne. 0) then
	      n_monarray=0
	    endif
	  endif
	endif
	if (axis2 .ne. ' ') then ! reduction axis
	  if (from .le. 0) then
	    if (to .eq. 0) to=999999
	    from=1
	  endif
	  if (to .lt. from) to=from
	  if (instr .eq. 'H' .or. xaxis .eq. 'x' .or. xaxis .eq. 'theta') then ! x on TriCS, theta on FOCUS
	    nsum=dim(1)
	    ngrp=1
	    nblk=dim(2)
	  else if (instr(1:1) .eq. 'R' .and. sdate .gt. '2006-12-20') then ! new rita
	    nsum=dim(1)
	    ngrp=1
	    nblk=dim(2)
	  else ! old rita or focus
	    nsum=dim(2)
	    ngrp=dim(1)
	    nblk=1
	  endif
	  if (from .gt. nsum) from=nsum
	  if (to .gt. nsum) to=nsum
	  if (from .eq. to) then
	    write(buf, '(9x,i7)') from
	  else
	    write(buf, '(i7,a,i7)') from,'..',to
	  endif
	  i=10
	  do while (buf(i:i) .eq. ' ')
	    i=i+1
	  enddo
	  buf(10:)=buf(i:)
	  i=1
	  do while (buf(i+1:i+1) .eq. ' ')
	    i=i+1
	  enddo
	  call pv('Range='//buf(i:), 0.0)
	  sta=(from+to)*0.5-1
          stp=to+1-from
	  length=dat_comp(2,0, p_array, nsum, ngrp, nblk
	1            , sta, stp, 1, p_weight)
	  if (n_monarray .gt. 0) then
	    i=dat_comp(0,0,p_monarray, nsum, ngrp, 1
	1         , sta, stp, 1, 0)
	    call dat_copy2f(p_monarray, weight, 1, 1)
	    if (ymon .ne. 0) then
	      weight = weight / ymon
	    endif
	  else
	    call dat_copy2f(p_weight, weight, 1, 1)
	  endif
	  if (icomp .gt. 1) then
	    stp=icomp
	    weight=weight*icomp
	    length=dat_comp(0,0, p_array, length,1,1,-0.5
	1	                ,stp,length/icomp,0)
	  endif
	else
	  weight=1
	endif
	if (nset .eq. 0) then
	  if (xlen .eq. 0) then
	    xlen=length
	    do i=1,length
	      xx(nread+i)=i
	    enddo
	  endif
	  if (length .ne. xlen) then
	    print *,'xaxis and signal length do not match', length, xlen
	  endif
	endif
	length=min(length,xlen)
	if (status .ne. NX_ok) then
	  print *,'signal ',signal,'not found'
	  goto 999
	endif
	if (length .gt. nmax) then
	  print *,'too large, data truncated from', length,' to',nmax
	  length=nmax
	endif
	call dat_copy2f(p_array, yy(nread+1), length, 1)
	if (ymon .eq. 0) ymon=1.
	totcnts=0.0
	ymon=ymon*weight
	do i=1,length
	  j=nread+i
	  totcnts=totcnts+yy(j)
	  ss(j)=sqrt(max(1.0,yy(j)))
	  ww(j)=ymon
	enddo
	if (nset .gt. 0) then
	  do i=1,length
	    xx(nread+i)=xx(i)
	  enddo
	endif
	nread=nread+length
	if (nframes .gt. 0 .and. iframe .le. 0) then
	  nset=nset+1
	  write(signal(1:10), '(a,i4.4)') '/frame',nset
	  if (nset .lt. nframes) goto 70
	  call fit_dat_table(1, 1, length)
	endif
	call dat_group(1, pv)
	call pv('Monitor', ymon)
	call pv('Counts', totcnts)
	i=NXclose(fileid)
	close(lun)
	call NXswitchReport(1)
!	call nxlistreport
	RETURN

999	i=NXclose(fileid)
	nread=-2
	call NXswitchReport(1)
!	call nxlistreport
	end


	subroutine dat_nexus_get(datapath)

	include 'dat_nexus.inc'

	character datapath*(*)
	
	character attr*64, nam*64, clss*64, low*64
	integer i, j, atype, l
        logical isdet
	integer start0(32)/32*0/
        real*8 dvalue

	logical end_of_path
	byte idata(257)

	integer dat_nexus_getslab
	
	if (datapath(1:1) .ne. '/') then
	  status=NX_error
	  RETURN
	endif
	do while (path(1:lp) .ne. datapath(1:min(lp,len(datapath))))
	  ! go up in path
	  status=NXclosegroup(fileid)
	  lp=lp-1
	  do while (path(lp:lp) .ne. '/')
	    lp=lp-1
	    if (lp .lt. 1) then
	      lp=1
	      path='/'
	      status=NX_error
	      RETURN
	    endif
	  enddo
	enddo

	end_of_path=.false.
10	continue ! loop
	  i=index(datapath(lp+1:), '/')-1
	  if (i .lt. 0) then
	    if (lp .eq. 1) then ! get global attribute
	      ! assume global attributes are all of type char
	      type=NX_char
	      length=len(cdata)
	      axis_signal=0
	      units=' '
	      name=datapath(2:)
	      status=NXgetattr(fileid, name, idata, length, type)
	      if (status .ne. NX_ok) RETURN
	      type=NX_char
	      call replace_string(cdata, idata)
	      if (length .le. 0) then
	        cdata=' '
	        length=1
	      endif
	      call str_trim(cdata, cdata(1:length), length)
	      RETURN
	    endif
	    call str_trim(datapath(lp+1:), datapath(lp+1:), i)
	    end_of_path=.true.
	  endif
	  call str_lowcase(low, datapath(lp+1:lp+i))
          isdet = low .eq. 'nxdetector'
	  status=NXinitgroupdir(fileid)
	  if (status .ne. NX_ok) RETURN
11	  status=NXgetnextentry(fileid, name, class, type)
	  do while (status .eq. NX_ok)
	    call str_lowcase(nam, name)
	    call str_lowcase(clss, class)
	    if (nam .eq. low .or. clss .eq. low) goto 12
            if (isdet .and. clss .eq. 'nxpsd') goto 12
	    if (low .eq. '*') then
	      if (nam .eq. xaxis) then
	        axis1=datapath(1:lp)//name
	        xaxis=name
	      else
	        status=NXopendata(fileid, name)
	        l=2
	        atype=NX_char
	        attr='axis'
	        status=NXgetattr(fileid, attr, axis_signal, l, atype)
	        if (status .eq. NX_ok
	1           .and. axis_signal .eq. ichar('1')
	1           .and. xaxis .eq. ' ') then
	          axis1=datapath(1:lp)//name
	          xaxis=name
	        endif
	      endif
	    endif
	    status=NXgetnextentry(fileid, name, class, type)
	  enddo
	  RETURN ! not found
12	  continue ! go down in path
	  if (end_of_path) goto 19
	  if (class .eq. 'SDS') goto 11 ! skip SDS when looking for groups
	  status=NXopengroup(fileid, name, class)
	  if (status .ne. NX_ok) RETURN
	  i=i+1
	  low(i:i)='/'
	  path(lp+1:)=low(1:i)
	  lp=lp+i
	  status=NXinitgroupdir(fileid)
	  i=index(datapath(lp+1:), '/')
	goto 10
19	continue ! open data
	status=NXopendata(fileid, name)
	if (status .ne. NX_ok) RETURN ! not found
	status=NXgetinfo(fileid, rank, dim, type)
	if (status .ne. NX_ok) goto 9
	if (rank .gt. 16) status=NX_error
	j=0
	length=1
	do i=1,rank
	  if (dim(i) .gt. 1) then
	    j=i
	    length=length*dim(i)
	  endif
	enddo
	rank0=rank
	if (j .eq. 0) then
	  dim(1)=1
	  rank=1
	else
	  rank=j
	endif
	if (rank .le. 1 .and. length .le. len(cdata) .and.
	1  (type .eq. nx_char .or.
	1   type .eq. nx_uint8 .or. type .eq. nx_int8)) then ! character (up to 256 chars)
	  type=nx_char
	  status=NXgetdata(fileid, idata)
	  if (status .ne. NX_ok) goto 9
	  call replace_string(cdata, idata)
	  call str_trim(cdata, cdata(1:length), length)
	elseif (rank .eq. 0) then ! scalar data
	  if (type .eq. nx_int32) then
	    status=NXgetdata(fileid, ivalue)
	    if (status .ne. NX_ok) goto 9
	    fvalue=ivalue
	  elseif (type .eq. nx_float32) then
	    status=NXgetdata(fileid, fvalue)
	    if (status .ne. NX_ok) goto 9
	  elseif (type .eq. nx_float64) then
	    dvalue = 0
	    status=NXgetdata(fileid, dvalue)
	    if (status .ne. NX_ok) goto 9
	    fvalue = dvalue
	  endif
	else
	  if (type .eq. nx_char) type=nx_uint8
	  status=dat_nexus_getslab(fileid, type, rank0, start0
	1                           , dim, p_array)
	  if (status .ne. NX_ok) goto 9
	endif
	status=NXgetnextattr(fileid, attr, l, atype)
	axis_signal=0
	units=' '
	do while (status .ne. NX_eod)
	  if (status .ne. NX_ok) goto 9
	  if (attr .eq. 'signal') then
	    axis_signal=-1
	  else if (attr .eq. 'axis') then
	    l=1
	    status=NXgetattr(fileid, attr, axis_signal, l, atype)
	  else if (attr .eq. 'units') then
	    l=len(units)
	    status=NXgetattr(fileid, attr, idata, l, atype)
	    call replace_string(cdata, idata)
	  endif	      
	  status=NXgetnextattr(fileid, attr, l, atype)
	enddo	    
	status=NXclosedata(fileid)
	RETURN

9	i=NXclosedata(fileid)
	end



	subroutine dat_nexus_r(pv, desc)

	include 'dat_nexus.inc'

	external pv
	character desc*(*)

	integer l,j,i
	character enam*64

	i=index(desc, '/')
	if (i .eq. 0) stop 'DAT_NEXUS_R: illegal descriptor'
	j=index(desc(1:i), instr)
	if (j .eq. 0) RETURN
	l=index(desc(i:), '=')
	if (l .eq. 0) then
	  call str_trim(desc, desc, l)
	  j=l
	  do while (desc(j:j) .ne. '/')
	    j=j-1
	  enddo
	  enam=desc(j+1:l)
	else
	  enam=desc(i+l:)
	  l=i+l-2
	endif
	call dat_nexus_get(desc(i:l))
	if (status .ne. NX_ok) then
	  ! optional items are marked with a question mark
	  if (index(desc(1:i), '?') .eq. 0) then
	    print *,'path ',desc(i:l),' not found'
	  endif
	else if (type .eq. nx_char) then
	  if (enam .eq. 'Date') then
	    sdate=cdata
	  endif
	  if (enam .eq. 'Preset') then
	    if (monitor .eq. 'auto') then
	      call str_lowcase(monitor, cdata)
	      if (monitor(1:1) .eq. 'm') then
	        monitor='smon'
	      else
	        monitor='time'
	      endif
	    endif
	  endif
	  call pv(enam//'='//cdata(1:length), 0.0)
	else if (type .eq. nx_int32 .or. type .eq. nx_float32 .or. type .eq. nx_float64) then
	  if (rank .gt. 0) call dat_nexus_average
	  if (enam .eq. 'frames' .and. nframes .gt. 0) then
	    nframes=nint(fvalue)
	  else
	    call pv(enam, fvalue)
	    call str_lowcase(enam, enam)
	    if (enam .eq. monitor) then
	      ymon=fvalue
	    endif
	  endif
	else
	  print *,enam,' has a strange type'
	  if (rank .gt. 0) then
	    call dat_copy2f(p_array, 0, 0, 1) ! free p_array
	  endif
	endif
	end

	subroutine dat_nexus_average

	include 'dat_nexus.inc'

	integer l
	integer dat_comp
	external dat_comp

	l=dat_comp(0,0,p_array,length,1,1,(length-1)*0.5,length*1.0,1,0)
	call dat_copy2f(p_array, fvalue, 1, 1)
	fvalue=fvalue/length
	end

	subroutine dat_nexus_putval(name, value)

	character name*(*)
	real value
	end
