~mok0/clipper/trunk

« back to all changes in this revision

Viewing changes to clipper/cns/cns_hkl_io.cpp

  • Committer: Morten Kjeldgaard
  • Date: 2011-02-09 21:25:56 UTC
  • Revision ID: mok@bioxray.dk-20110209212556-3zbon5ukh4zf3x00
Tags: 2.0.3
versionĀ 2.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* cns_hkl_io.cpp: class file for reflection data  cns_hkl importer */
 
2
//C Copyright (C) 2000-2006 Kevin Cowtan and University of York
 
3
//L
 
4
//L  This library is free software and is distributed under the terms
 
5
//L  and conditions of version 2.1 of the GNU Lesser General Public
 
6
//L  Licence (LGPL) with the following additional clause:
 
7
//L
 
8
//L     `You may also combine or link a "work that uses the Library" to
 
9
//L     produce a work containing portions of the Library, and distribute
 
10
//L     that work under terms of your choice, provided that you give
 
11
//L     prominent notice with each copy of the work that the specified
 
12
//L     version of the Library is used in it, and that you include or
 
13
//L     provide public access to the complete corresponding
 
14
//L     machine-readable source code for the Library including whatever
 
15
//L     changes were used in the work. (i.e. If you make changes to the
 
16
//L     Library you must distribute those, but you do not need to
 
17
//L     distribute source or object code to those portions of the work
 
18
//L     not covered by this licence.)'
 
19
//L
 
20
//L  Note that this clause grants an additional right and does not impose
 
21
//L  any additional restriction, and so does not affect compatibility
 
22
//L  with the GNU General Public Licence (GPL). If you wish to negotiate
 
23
//L  other terms, please contact the maintainer.
 
24
//L
 
25
//L  You can redistribute it and/or modify the library under the terms of
 
26
//L  the GNU Lesser General Public License as published by the Free Software
 
27
//L  Foundation; either version 2.1 of the License, or (at your option) any
 
28
//L  later version.
 
29
//L
 
30
//L  This library is distributed in the hope that it will be useful, but
 
31
//L  WITHOUT ANY WARRANTY; without even the implied warranty of
 
32
//L  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
33
//L  Lesser General Public License for more details.
 
34
//L
 
35
//L  You should have received a copy of the CCP4 licence and/or GNU
 
36
//L  Lesser General Public License along with this library; if not, write
 
37
//L  to the CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
 
38
//L  The GNU Lesser General Public can also be obtained by writing to the
 
39
//L  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
40
//L  MA 02111-1307 USA
 
41
 
 
42
#include "cns_hkl_io.h"
 
43
 
 
44
extern "C" {
 
45
#include <stdio.h>
 
46
}
 
47
 
 
48
 
 
49
namespace clipper {
 
50
 
 
51
 
 
52
clipper::String cnstok( FILE* f ) {
 
53
  String s;
 
54
  char c = fgetc( f );
 
55
  while ( c > '\0' && c < ' ' ) c = fgetc( f );
 
56
  while ( c > ' ' && c != '=') {
 
57
    s += c;
 
58
    c = fgetc( f );
 
59
  }
 
60
  return s;
 
61
}
 
62
 
 
63
 
 
64
/*! Constructing an CNS_HKLfile does nothing except flag the object as not
 
65
  attached to any file for either input or output */
 
66
CNS_HKLfile::CNS_HKLfile()
 
67
{
 
68
  mode = NONE;
 
69
}
 
70
 
 
71
 
 
72
/*! Close any files which were left open. This is particularly
 
73
  important since to access the CNS_HKL file efficiently, data reads and
 
74
  writes are deferred until the file is closed. */
 
75
CNS_HKLfile::~CNS_HKLfile()
 
76
{
 
77
  switch ( mode ) {
 
78
  case READ:
 
79
    close_read(); break;
 
80
  case WRITE:
 
81
    close_write(); break;
 
82
  case NONE:
 
83
    break;
 
84
  }
 
85
}
 
86
 
 
87
 
 
88
/*! The file is opened for reading. This CNS_HKLfile object will remain
 
89
  attached to this file until it is closed. Until that occurs, no
 
90
  other file may be opened with this object, however another CNS_HKLfile
 
91
  object could be used to access another file.
 
92
  \param filename_in The input filename or pathname. */
 
93
void CNS_HKLfile::open_read( const String filename_in )
 
94
{
 
95
  if ( mode != NONE )
 
96
    Message::message( Message_fatal( "CNS_HKLfile: open_read - File already open" ) );
 
97
 
 
98
  // open the cns_hkl
 
99
  f_sigf_i = NULL; phi_wt_i = NULL; f_phi_i = NULL; abcd_i = NULL; flag_i = NULL;
 
100
  filename = filename_in;
 
101
 
 
102
  FILE* cns_hkl = fopen( filename.c_str(), "r" );
 
103
  if ( cns_hkl == NULL )
 
104
    Message::message( Message_fatal( "CNS_HKLfile: open_read  - Could not read: "+filename ) );
 
105
  fclose( cns_hkl );
 
106
 
 
107
  mode = READ;
 
108
}
 
109
 
 
110
 
 
111
/*! Close the file after reading. This command also actually fills in
 
112
  the data in any HKL_data structures which have been marked for
 
113
  import. */
 
114
void CNS_HKLfile::close_read()
 
115
{
 
116
  if ( mode != READ )
 
117
    Message::message( Message_fatal( "CNS_HKLfile: no file open for read" ) );
 
118
 
 
119
  // make sure the data list is sized
 
120
  if ( f_sigf_i != NULL ) f_sigf_i->update();
 
121
  if ( phi_wt_i != NULL ) phi_wt_i->update();
 
122
  if ( f_phi_i  != NULL ) f_phi_i->update();
 
123
  if ( abcd_i   != NULL ) abcd_i->update();
 
124
  if ( flag_i   != NULL ) flag_i->update();
 
125
 
 
126
 
 
127
  int h, k, l;
 
128
  xtype fo[8], pw[8], fc[8], hl[8], fl[8];
 
129
  h = k = l = 0;
 
130
  HKL hkl;
 
131
 
 
132
  FILE* cns_hkl = fopen( filename.c_str(), "r" );
 
133
  if ( cns_hkl == NULL )
 
134
    Message::message( Message_fatal( "CNS_HKLfile: import_hkl_data  - Could not read: "+filename ) );
 
135
  // read the data from the CNS_HKL
 
136
  int code = 0;
 
137
  String s, t;
 
138
  while ( (s=cnstok(cns_hkl)).length() > 0 ) {
 
139
    t = (s+"   ").substr(0,4);
 
140
    if ( t == "INDE" ) {
 
141
      if (h||k||l) {
 
142
        hkl = HKL( h, k, l );
 
143
        if ( f_sigf_i != NULL ) f_sigf_i->data_import( hkl, fo );
 
144
        if ( phi_wt_i != NULL ) phi_wt_i->data_import( hkl, pw );
 
145
        if ( f_phi_i  != NULL ) f_phi_i->data_import( hkl, fc );
 
146
        if ( abcd_i   != NULL ) abcd_i->data_import( hkl, hl );
 
147
        if ( flag_i   != NULL ) flag_i->data_import( hkl, fl );
 
148
      }
 
149
      h = k = l = 0;
 
150
      for ( int i = 0; i < 8; i++ ) fo[i] = pw[i] = fc[i] = hl[i] = fl[i] = 0.0;
 
151
    }
 
152
    if      ( t == "INDE" ) code = 10;
 
153
    else if ( t == "FOBS" ) code = 20;
 
154
    else if ( t == "SIGM" ) code = 30;
 
155
    else if ( t == "FOM " ) code = 40;
 
156
    else if ( t == "FCAL" ) code = 50;
 
157
    else if ( t == "ABCD" ) code = 60;
 
158
    else if ( t == "TEST" ) code = 70;
 
159
    else if ( code == 10 ) { h = s.i(); code++; }
 
160
    else if ( code == 11 ) { k = s.i(); code++; }
 
161
    else if ( code == 12 ) { l = s.i(); code++; }
 
162
    else if ( code == 20 ) { fo[0] = s.f(); code++; }
 
163
    else if ( code == 21 ) { pw[0] = s.f(); code++; }
 
164
    else if ( code == 30 ) { fo[1] = s.f(); code++; }
 
165
    else if ( code == 40 ) { pw[1] = s.f(); code++; }
 
166
    else if ( code == 50 ) { fc[0] = s.f(); code++; }
 
167
    else if ( code == 51 ) { fc[1] = s.f(); code++; }
 
168
    else if ( code == 60 ) { hl[0] = s.f(); code++; }
 
169
    else if ( code == 61 ) { hl[1] = s.f(); code++; }
 
170
    else if ( code == 62 ) { hl[2] = s.f(); code++; }
 
171
    else if ( code == 63 ) { hl[3] = s.f(); code++; }
 
172
    else if ( code == 70 ) { fl[0] = s.f(); code++; }
 
173
  }
 
174
  if (h||k||l) {  // get last rfl
 
175
    hkl = HKL( h, k, l );
 
176
    if ( f_sigf_i != NULL ) f_sigf_i->data_import( hkl, fo );
 
177
    if ( phi_wt_i != NULL ) phi_wt_i->data_import( hkl, pw );
 
178
    if ( f_phi_i  != NULL ) f_phi_i->data_import( hkl, fc );
 
179
    if ( abcd_i   != NULL ) abcd_i->data_import( hkl, hl );
 
180
    if ( flag_i   != NULL ) flag_i->data_import( hkl, fl );
 
181
  }
 
182
  fclose( cns_hkl );
 
183
 
 
184
  mode = NONE;
 
185
}
 
186
 
 
187
 
 
188
/*! The file is opened for writing. This will be a new file, created
 
189
  entirely from data from within the program, rather than by extending
 
190
  an existing file. Similar restrictions apply as for open_read().
 
191
 
 
192
  \param filename_out The output filename or pathname. */
 
193
void CNS_HKLfile::open_write( const String filename_out )
 
194
{
 
195
  if ( mode != NONE )
 
196
    Message::message( Message_fatal( "CNS_HKLfile: open_write - File already open" ) );
 
197
 
 
198
  // open the output cns_hkl
 
199
  hkl_ptr = NULL;
 
200
  f_sigf_o = NULL; phi_wt_o = NULL; f_phi_o = NULL; abcd_o = NULL; flag_o = NULL;
 
201
  filename = filename_out;
 
202
 
 
203
  FILE* cns_hkl = fopen( filename.c_str(), "w" );
 
204
  if ( cns_hkl == NULL )
 
205
    Message::message( Message_fatal( "CNS_HKLfile: open_write - Could not write: "+filename ) );
 
206
  fclose( cns_hkl );
 
207
 
 
208
  mode = WRITE;
 
209
}
 
210
 
 
211
 
 
212
/*! Close the file after writing. This command also actually writes
 
213
  the data reflection list from the HKL_info object and the data from
 
214
  any HKL_data objects which have been marked for import. */
 
215
void CNS_HKLfile::close_write()
 
216
{
 
217
  if ( mode != WRITE )
 
218
    Message::message( Message_fatal( "CNS_HKLfile: close_write - no file open for write" ) );
 
219
 
 
220
  // export the marked list data to an cns_hkl file
 
221
  if ( hkl_ptr == NULL )
 
222
    Message::message( Message_fatal( "CNS_HKLfile: close_write - no refln list exported" ) );
 
223
  const HKL_info& hklinf = *hkl_ptr;
 
224
 
 
225
  HKL hkl;
 
226
  xtype x[4];
 
227
  float f1, f2, f3, f4;
 
228
 
 
229
  FILE* cns_hkl = fopen( filename.c_str(), "w" );
 
230
  if ( cns_hkl == NULL )
 
231
    Message::message( Message_fatal( "CNS_HKLfile: close_write - Could not write: "+filename ) );
 
232
  fprintf( cns_hkl, "NREF=%i\n", hklinf.num_reflections() );
 
233
  HKL_info::HKL_reference_index ih;
 
234
  for ( ih = hklinf.first(); !ih.last(); ih.next() ) {
 
235
    f1 = f2 = f3 = f4 = 0.0;  // default sigf to 0 in case missing
 
236
    hkl = ih.hkl();
 
237
    fprintf( cns_hkl, "INDE %i %i %i", hkl.h(), hkl.k(), hkl.l() );
 
238
    if ( f_sigf_o != NULL ) {
 
239
      f_sigf_o->data_export( hkl, x );
 
240
      for ( int i = 0; i < 4; i++ ) if ( Util::is_nan(x[i]) ) x[i] = 0.0;
 
241
      f1 = float( x[0] );
 
242
      f2 = float( x[1] );
 
243
    }
 
244
    if ( phi_wt_o != NULL ) {
 
245
      phi_wt_o->data_export( hkl, x );
 
246
      for ( int i = 0; i < 4; i++ ) if ( Util::is_nan(x[i]) ) x[i] = 0.0;
 
247
      f3 = float( x[0] );
 
248
      f4 = float( x[1] );
 
249
    }
 
250
    fprintf( cns_hkl, " FOBS=%.3f %.3f SIGM=%.3f FOM=%.3f",f1,f3,f2,f4 );
 
251
    if ( f_phi_o != NULL ) {
 
252
      f_phi_o->data_export( hkl, x );
 
253
      for ( int i = 0; i < 4; i++ ) if ( Util::is_nan(x[i]) ) x[i] = 0.0;
 
254
      fprintf( cns_hkl, " FCAL=%.3f %.3f",float(x[0]),float(x[1]) );
 
255
    }
 
256
    if ( abcd_o != NULL ) {
 
257
      abcd_o->data_export( hkl, x );
 
258
      for ( int i = 0; i < 4; i++ ) if ( Util::is_nan(x[i]) ) x[i] = 0.0;
 
259
      fprintf( cns_hkl, " HLA=%.1f HLB=%.1f HLC=%.1f HLD=%.1f",float(x[0]),float(x[1]),float(x[2]),float(x[3]) );
 
260
    }
 
261
    if ( flag_o != NULL ) {
 
262
      abcd_o->data_export( hkl, x );
 
263
      for ( int i = 0; i < 4; i++ ) if ( Util::is_nan(x[i]) ) x[i] = 0.0;
 
264
      fprintf( cns_hkl, " TEST=%i",Util::intr(x[0]) );
 
265
    }
 
266
    fprintf( cns_hkl, "\n" );
 
267
  }
 
268
  fclose( cns_hkl );
 
269
 
 
270
  mode = NONE;
 
271
}
 
272
 
 
273
 
 
274
/*! Get the resolution limit from the CNS_HKL file.
 
275
  Since a CNS_HKL file does not contain cell information, a Cell object
 
276
  must be supplied, which will be used to determine the resultion.
 
277
  The result is the resolution determined by the most extreme
 
278
  reflection in the file.
 
279
  \return The resolution. */
 
280
Resolution CNS_HKLfile::resolution( const Cell& cell ) const
 
281
{
 
282
  if ( mode != READ )
 
283
    Message::message( Message_fatal( "CNS_HKLfile: resolution - no file open for read" ) );
 
284
 
 
285
  HKL hkl;
 
286
  int h, k, l;
 
287
  FILE* cns_hkl = fopen( filename.c_str(), "r" );
 
288
  if ( cns_hkl == NULL )
 
289
    Message::message( Message_fatal( "CNS_HKLfile: resolution - Could not read: "+filename ) );
 
290
  // read the reflections from the cns_hkl
 
291
  ftype slim = 0.0;
 
292
  String s, t;
 
293
  while ( (s=cnstok(cns_hkl)).length() > 0 ) {
 
294
    t = (s+"   ").substr(0,4);
 
295
    if ( t == "INDE" ) {
 
296
      h = cnstok(cns_hkl).i();
 
297
      k = cnstok(cns_hkl).i();
 
298
      l = cnstok(cns_hkl).i();
 
299
      hkl = HKL( h, k, l );
 
300
      slim = Util::max( slim, hkl.invresolsq(cell) );
 
301
    }
 
302
  }
 
303
  fclose( cns_hkl );
 
304
 
 
305
  return Resolution( 1.0/sqrt(slim) );
 
306
}
 
307
 
 
308
 
 
309
/*! Import the list of reflection HKLs from an CNS_HKL file into an
 
310
  HKL_info object. If the resolution limit of the HKL_info object is
 
311
  lower than the limit of the file, any excess reflections will be
 
312
  rejected, as will any systematic absences or duplicates.
 
313
  \param target The HKL_info object to be initialised. */
 
314
void CNS_HKLfile::import_hkl_info( HKL_info& target )
 
315
{
 
316
  if ( mode != READ )
 
317
    Message::message( Message_fatal( "CNS_HKLfile: import_hkl_info - no file open for read" ) );
 
318
 
 
319
  std::vector<HKL> hkls;
 
320
  HKL hkl;
 
321
  int h, k, l;
 
322
  FILE* cns_hkl = fopen( filename.c_str(), "r" );
 
323
  if ( cns_hkl == NULL )
 
324
    Message::message( Message_fatal( "CNS_HKLfile: import_hkl_info - Could not read: "+filename ) );
 
325
  // read the reflections from the cns_hkl
 
326
  ftype slim = target.resolution().invresolsq_limit();
 
327
  String s, t;
 
328
  while ( (s=cnstok(cns_hkl)).length() > 0 ) {
 
329
    t = (s+"   ").substr(0,4);
 
330
    if ( t == "INDE" ) {
 
331
      h = cnstok(cns_hkl).i();
 
332
      k = cnstok(cns_hkl).i();
 
333
      l = cnstok(cns_hkl).i();
 
334
      hkl = HKL( h, k, l );
 
335
      if ( hkl.invresolsq(target.cell()) < slim ) hkls.push_back( hkl );
 
336
    }
 
337
  }
 
338
  fclose( cns_hkl );
 
339
 
 
340
  target.add_hkl_list( hkls );
 
341
}
 
342
 
 
343
 
 
344
/*! Import data from an CNS_HKL file into an HKL_data object.
 
345
 
 
346
  This routine does not actually read any data, but rather marks the
 
347
  data to be read when the file is closed.
 
348
 
 
349
  The data to be read (F_sigF or Phi_fom) will be selected based on
 
350
  the type of the HKL_data object.
 
351
 
 
352
  \param cdata The HKL_data object into which data is to be imported. */
 
353
void CNS_HKLfile::import_hkl_data( HKL_data_base& cdata )
 
354
{
 
355
  if ( mode != READ )
 
356
    Message::message( Message_fatal( "CNS_HKLfile: import_hkl_data - no file open for read" ) );
 
357
 
 
358
  if      ( cdata.type() == data32::F_sigF::type()  ) f_sigf_i = &cdata;
 
359
  else if ( cdata.type() == data32::Phi_fom::type() ) phi_wt_i = &cdata;
 
360
  else if ( cdata.type() == data32::F_phi::type() )   f_phi_i  = &cdata;
 
361
  else if ( cdata.type() == data32::ABCD::type() )    abcd_i   = &cdata;
 
362
  else if ( cdata.type() == data32::Flag::type() )    flag_i   = &cdata;
 
363
  else
 
364
    Message::message( Message_fatal( "CNS_HKLfile: import_hkl_data - data must be F_sigF/Phi_fom/F_phi/ABCD/Flag" ) );
 
365
}
 
366
 
 
367
 
 
368
/*! Export the list of reflection HKLs to an CNS_HKL file from an
 
369
  HKL_info object. */
 
370
void CNS_HKLfile::export_hkl_info( const HKL_info& target )
 
371
{
 
372
  if ( mode != WRITE )
 
373
    Message::message( Message_fatal( "CNS_HKLfile: export_hkl_info - no file open for write" ) );
 
374
  hkl_ptr = &target;
 
375
}
 
376
 
 
377
 
 
378
/*! Export data from an HKL_data object into an CNS_HKL file.
 
379
 
 
380
  This routine does not actually write any data, but rather marks the
 
381
  data to be written when the file is closed.
 
382
 
 
383
  The data to be read (F_sigF or Phi_fom) will be selected based on
 
384
  the type of the HKL_data object.
 
385
 
 
386
  \param cdata The HKL_data object from which data is to be exported. */
 
387
void CNS_HKLfile::export_hkl_data( const HKL_data_base& cdata )
 
388
{
 
389
  if ( mode != WRITE )
 
390
    Message::message( Message_fatal( "CNS_HKLfile: export_hkl_data - no file open for write" ) );
 
391
 
 
392
  if      ( cdata.type() == data32::F_sigF::type()  ) f_sigf_o = &cdata;
 
393
  else if ( cdata.type() == data32::Phi_fom::type() ) phi_wt_o = &cdata;
 
394
  else if ( cdata.type() == data32::F_phi::type() )   f_phi_o  = &cdata;
 
395
  else if ( cdata.type() == data32::ABCD::type() )    abcd_o   = &cdata;
 
396
  else if ( cdata.type() == data32::Flag::type() )    flag_o   = &cdata;
 
397
  else
 
398
    Message::message( Message_fatal( "CNS_HKLfile: export_hkl_data - data must be F_sigF/Phi_fom/F_phi/ABCD/Flag" ) );
 
399
}
 
400
 
 
401
 
 
402
} // namespace clipper